#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Ford UK NGc2 爬虫核心模块 - 重构版
使用模块化架构，导入新的Ford爬虫实现

重构说明：
- 原来的4000+行代码已拆分为多个功能模块
- 每个模块专注于特定功能，便于维护和扩展
- 保持了原有的接口兼容性

模块结构：
- base.py: WebDriver管理和基础工具
- navigation.py: 页面导航和Cookie处理
- drive_handler.py: Drive配置抓取
- bodystyle_handler.py: 车身样式抓取  
- colour_handler.py: 颜色配置抓取
- interior_handler.py: 内饰配置抓取
- extras_handler.py: 选装件抓取
- model_scraper.py: 基础车型数据抓取
- ford_scraper.py: 主协调器
"""

# 导入重构后的Ford爬虫主类
from .ford_scraper import FordScraper as NewFordScraper, FordScraperLegacy

# 导入实体类（保持不变）
from .car_series import CarSeries
from .car_object import CarObject
from .car_extras import CarExtras


# 为了保持向后兼容性，创建一个别名
# 新的实现在ford_scraper.py中，原来的大文件已拆分为多个模块
class FordScraper(FordScraperLegacy):
    """
    Ford UK 网站爬虫类 - 重构版
    
    这是一个兼容性包装器，实际实现已拆分到多个专门的模块中：
    - 基础设施模块 (base.py)
    - 导航模块 (navigation.py) 
    - Drive处理模块 (drive_handler.py)
    - Bodystyle处理模块 (bodystyle_handler.py)
    - Colour处理模块 (colour_handler.py)
    - Interior处理模块 (interior_handler.py)
    - Extras处理模块 (extras_handler.py)
    - 模型抓取模块 (model_scraper.py)
    - 主协调器 (ford_scraper.py)
    
    优势：
    - 代码结构更清晰，每个模块职责单一
    - 更易于维护和扩展
    - 更好的测试支持
    - 更低的耦合度
    """
    
    def __init__(self, config):
        """
        初始化爬虫 - 重构版
        
        Args:
            config (dict): 配置信息
        """
        # 调用新架构的初始化
        super().__init__(config)
        
        # 打印重构信息
        print("🔄 使用重构版Ford爬虫 (模块化架构)")
        print("📁 代码已拆分为8个专门的功能模块，提升维护性")


# 重构说明：
# 原来的4000+行代码已经重构为模块化架构
# 所有功能方法都已转移到对应的专门模块中
# 这个文件现在只作为兼容性接口保留

    
    def run(self):
        """主执行流程 - 集成车型选择和配置流程"""
        try:
            print("🚀 开始数据抓取流程...")
            
            # 第一阶段：基础页面加载和Cookie处理
            print("\n=== 第一阶段：页面初始化 ===")
            url = self.config['sub_model']['url']
            print(f"🌐 正在访问: {url}")
            self.driver.get(url)
            
            # 等待页面加载
            self.wait_for_page_load()
            
            # 处理cookie同意弹窗
            self.handle_cookie_consent()
            
            # 第二阶段：基础车型数据抓取
            print("\n=== 第二阶段：基础车型数据抓取 ===")
            car_series = self.scrape_model_data()
            
            # 第三阶段：车型选择和配置流程
            print("\n=== 第三阶段：车型选择和配置流程 ===")
            
            # 从配置中获取目标车型名称（如果指定）
            target_model = self.config.get('target_model')
            if not target_model and car_series.car_object_list:
                # 如果没有指定，默认选择第一个检测到的车型
                target_model = car_series.car_object_list[0].model_name
                print(f"🎨 未指定目标车型，默认选择: {target_model}")
            
            if target_model:
                # 选择车型并进入配置流程
                config_success = self.select_model_and_enter_configuration(target_model)
                
                if config_success:
                    # 第四阶段：完整配置数据抓取
                    print("\n=== 第四阶段：配置数据抓取 ===")
                    enhanced_car_series = self.scrape_configuration_data(car_series, target_model)
                    
                    # 保存增强后的数据
                    self.save_data(enhanced_car_series)
                else:
                    print(f"⚠️  配置流程进入失败，保存基础数据")
                    self.save_data(car_series)
            else:
                print(f"⚠️  未检测到可用车型，仅保存基础数据")
                self.save_data(car_series)
            
            print("\n✅ 数据抓取流程完成!")
            
        except Exception as e:
            print(f"❌ 数据抓取过程中出错: {e}")
            raise
        finally:
            self.cleanup()
    
    def scrape_configuration_data(self, car_series, target_model):
        """
        抓取完整的配置数据（Drive, Bodystyle, Colour, Interior, Extras）
        
        Args:
            car_series (CarSeries): 基础车系数据
            target_model (str): 目标车型名称
            
        Returns:
            CarSeries: 增强后的车系数据
        """
        print(f"🔧 开始抓取 {target_model} 的完整配置数据...")
        
        try:
            # 步骤1：进入Drive页面并抓取Drive数据
            print("  🚗 抓取Drive数据...")
            drive_data = self.scrape_drive_data()
            
            if drive_data:
                print(f"  🎯 找到 {len(drive_data)} 个真正的Drive选项")
                
                # 步骤2：根据新业务逻辑，为每个Drive创建独立的CarObject
                self.update_car_objects_with_drive_data(car_series, target_model, drive_data)
                
                # 步骤3：循环每个Drive选项，进入Bodystyle页面
                print("  🎨 开始循环Drive类型抓取Bodystyle数据...")
                all_bodystyle_data = self.scrape_bodystyle_for_all_drives(drive_data)
                
                # 将Bodystyle数据添加到对应的CarObject中
                if all_bodystyle_data:
                    self.update_car_objects_with_bodystyle_data(car_series, target_model, all_bodystyle_data)
            else:
                print("  ⚠️  未找到有效的Drive选项，跳过Bodystyle抓取")
            
            # 步骤4：进入Colour页面并滚动抓取
            print("  🌈 抓取Colour数据...")
            colour_data = self.scrape_colour_data()
            
            # 将Colour数据添加到每个CarObject中
            if colour_data:
                self.update_car_objects_with_colour_data(car_series, target_model, colour_data)
            
            # 步骤5：进入Interior页面
            print("  🪑 抓取Interior数据...")
            interior_data = self.scrape_interior_data()
            
            # 将Interior数据添加到每个CarObject中
            if interior_data:
                self.update_car_objects_with_interior_data(car_series, target_model, interior_data)
            
            # 步骤6：进入Extras页面
            print("  ⚙️  抓取Extras数据...")
            extras_data = self.scrape_extras_data()
            
            # 将Extras数据添加到每个CarObject中
            if extras_data:
                self.update_car_objects_with_extras_data(car_series, target_model, extras_data)
            
            print(f"  ✅ {target_model} 配置数据抓取完成（阶段2）")
            return car_series
            
        except Exception as e:
            print(f"  ❌ 配置数据抓取出错: {e}")
            return car_series
    

    
    def scrape_bodystyle_for_all_drives(self, drive_options):
        """
        循环每个Drive选项，进入Bodystyle页面并抓取数据
        
        Args:
            drive_options (list): 过滤后的真正Drive选项
            
        Returns:
            dict: 每个Drive选项对应的Bodystyle数据
        """
        all_bodystyle_data = {}
        
        for i, drive_option in enumerate(drive_options, 1):
            drive_name = drive_option.get('name', '')
            print(f"    🚗 处理Drive {i}/{len(drive_options)}: {drive_name}")
            
            try:
                # 选择当前Drive选项
                if self.select_drive_option(drive_option):
                    # 进入Bodystyle页面
                    if self.navigate_to_bodystyle_page():
                        # 抓取Bodystyle数据
                        bodystyle_data = self.scrape_bodystyle_data()
                        if bodystyle_data:
                            all_bodystyle_data[drive_name] = bodystyle_data
                            print(f"      ✅ {drive_name} 的Bodystyle数据抓取成功: {len(bodystyle_data)} 个选项")
                        else:
                            print(f"      ⚠️  {drive_name} 未抓取到Bodystyle数据")
                    else:
                        print(f"      ❌ 无法进入 {drive_name} 的Bodystyle页面")
                else:
                    print(f"      ❌ 无法选择Drive选项: {drive_name}")
                    
            except Exception as e:
                print(f"      ❌ 处理Drive {drive_name} 时出错: {e}")
                continue
            
            # 在处理下一个选项前稍作等待
            if i < len(drive_options):
                time.sleep(2)
        
        print(f"  🎯 循环完成，共为 {len(all_bodystyle_data)} 个Drive选项抓取了Bodystyle数据")
        return all_bodystyle_data
    
    def select_drive_option(self, drive_option):
        """
        选择指定的Drive选项，点击与其在同一DIV内的Selected按钮
        
        Args:
            drive_option (dict): Drive选项数据
            
        Returns:
            bool: 是否成功选择
        """
        drive_name = drive_option.get('name', '')
        print(f"      🔍 选择Drive选项: {drive_name}")
        
        try:
            # 优先使用已经找到的Selected按钮
            selected_button = drive_option.get('selected_button')
            
            if selected_button:
                try:
                    print(f"        ✓ 使用已找到的Selected按钮")
                    self.click_element_safely(selected_button)
                    time.sleep(2)
                    print(f"        ✅ 成功选择Drive: {drive_name}")
                    return True
                except Exception as click_error:
                    print(f"        ⚠️  点击Selected按钮失败: {click_error}")
            
            # 如果没有预先找到的按钮，重新查找
            print(f"        🔍 重新查找Drive选项和Selected按钮...")
            
            # 查找所有ProductTileMainValue元素
            drive_main_elements = self.driver.find_elements(
                By.CSS_SELECTOR, 
                'span.ProductTileSection__ProductTileMainValue-sc-5noent-16'
            )
            
            for drive_element in drive_main_elements:
                if drive_element.is_displayed():
                    element_text = drive_element.text.strip()
                    
                    # 检查是否匹配当前Drive
                    if element_text == drive_name or drive_name in element_text:
                        print(f"        ✓ 找到匹配Drive元素: {element_text}")
                        
                        # 查找对应的Selected按钮
                        selected_button = self.find_selected_button_for_drive(drive_element)
                        
                        if selected_button:
                            try:
                                print(f"        ✓ 找到对应的Selected按钮")
                                self.click_element_safely(selected_button)
                                time.sleep(2)
                                print(f"        ✅ 成功选择Drive: {drive_name}")
                                return True
                            except Exception as click_error:
                                print(f"        ⚠️  点击Selected按钮失败: {click_error}")
                                continue
                        else:
                            print(f"        ⚠️  未找到对应的Selected按钮")
            
            # 如果仍未成功，尝试通用Selected按钮
            print(f"        🔍 未找到精确匹配，尝试通用Selected按钮...")
            select_buttons = self.driver.find_elements(By.CSS_SELECTOR, 'button')
            
            for button in select_buttons:
                if button.is_displayed() and button.is_enabled():
                    button_text = button.text.strip().lower()
                    if 'select' in button_text and len(button_text) < 20:
                        try:
                            self.click_element_safely(button)
                            time.sleep(2)
                            print(f"        ✅ 使用通用Select按钮选择Drive")
                            return True
                        except Exception:
                            continue
            
            print(f"        ❌ 未找到可点击的Drive选项: {drive_name}")
            return False
            
        except Exception as e:
            print(f"        ❌ 选择Drive选项时出错: {e}")
            return False
    
    def navigate_to_bodystyle_page(self):
        """
        导航到Bodystyle配置页面
        
        Returns:
            bool: 是否成功进入Bodystyle页面
        """
        print(f"        🧭 导航到Bodystyle页面...")
        
        try:
            # 等待页面更新后再导航
            time.sleep(2)
            
            # 方法1：查找导航栏中的Bodystyle按钮
            nav_state = self.get_navigation_state()
            if nav_state and 'Bodystyle' in nav_state:
                bodystyle_nav_info = nav_state['Bodystyle']
                
                if (bodystyle_nav_info.get('enabled', False) and 
                    bodystyle_nav_info.get('aria_disabled', 'true') == 'false'):
                    
                    bodystyle_button = self.find_navigation_button('Bodystyle')
                    if bodystyle_button:
                        print(f"          ✓ 找到Bodystyle导航按钮")
                        self.click_element_safely(bodystyle_button)
                        time.sleep(2)
                        
                        if self.verify_bodystyle_page_loaded():
                            print(f"          ✅ 成功进入Bodystyle页面")
                            return True
            
            # 方法2：查找Bodystyle相关的直接链接
            bodystyle_selectors = [
                'a[href*="bodystyle"]',
                'button[data-testid*="bodystyle"]',
                '[class*="Bodystyle"] button',
                'button[aria-label*="bodystyle" i]',
                'button[aria-label*="body style" i]'
            ]
            
            for selector in bodystyle_selectors:
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    for element in elements:
                        if element.is_displayed() and element.is_enabled():
                            print(f"          ✓ 找到Bodystyle链接: {selector}")
                            self.click_element_safely(element)
                            time.sleep(2)
                            
                            if self.verify_bodystyle_page_loaded():
                                print(f"          ✅ 通过直接链接进入Bodystyle页面")
                                return True
                except Exception:
                    continue
            
            # 方法3：检查当前URL是否已经在Bodystyle页面
            current_url = self.driver.current_url.lower()
            if 'bodystyle' in current_url or 'body' in current_url:
                print(f"          ✓ 当前URL显示已在Bodystyle页面")
                return self.verify_bodystyle_page_loaded()
            
            print(f"          ❌ 所有Bodystyle导航方法都失败")
            return False
            
        except Exception as e:
            print(f"          ❌ 导航到Bodystyle页面时出错: {e}")
            return False
    
    def verify_bodystyle_page_loaded(self):
        """
        验证Bodystyle页面是否已加载
        
        Returns:
            bool: 是否已加载Bodystyle页面
        """
        try:
            # 检查方法1：查找Bodystyle相关的页面元素
            bodystyle_indicators = [
                '[data-testid*="bodystyle"]',
                '[data-testid*="body"]',
                '[class*="Bodystyle"]',
                '[class*="BodyStyle"]',
                'h1, h2, h3[class*="body" i]',
                'h1, h2, h3[class*="style" i]'
            ]
            
            for selector in bodystyle_indicators:
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    if elements:
                        visible_elements = [el for el in elements if el.is_displayed()]
                        if visible_elements:
                            print(f"          ✓ 检测到Bodystyle页面元素: {selector}")
                            return True
                except Exception:
                    continue
            
            # 检查方法2：URL验证
            current_url = self.driver.current_url.lower()
            if 'bodystyle' in current_url or 'body' in current_url:
                print(f"          ✓ URL显示在Bodystyle页面")
                return True
            
            # 检查方法3：导航状态
            nav_state = self.get_navigation_state()
            if nav_state and 'Bodystyle' in nav_state:
                bodystyle_info = nav_state['Bodystyle']
                if bodystyle_info.get('current', False):
                    print(f"          ✓ 导航状态显示在Bodystyle页面")
                    return True
            
            return False
            
        except Exception as e:
            print(f"          验证Bodystyle页面时出错: {e}")
            return False
    
    def scrape_bodystyle_data(self):
        """
        抓取Bodystyle页面的数据
        只识别 ProductTileSection__ProductTileAttributeValue 标签内的内容作为BodyStyle
        
        Returns:
            list: Bodystyle选项列表
        """
        print(f"          🔍 抓取Bodystyle选项...")
        
        bodystyle_options = []
        
        try:
            # 等待页面稳定
            time.sleep(2)
            
            # 根据用户澄清的业务逻辑：只有ProductTileAttributeValue标签内的内容才是BodyStyle
            bodystyle_attribute_selector = 'strong.ProductTileSection__ProductTileAttributeValue-sc-5noent-23'
            
            # 查找所有BodyStyle属性值元素
            bodystyle_elements = self.driver.find_elements(By.CSS_SELECTOR, bodystyle_attribute_selector)
            
            print(f"            🔍 找到 {len(bodystyle_elements)} 个ProductTileAttributeValue元素")
            
            for i, bodystyle_element in enumerate(bodystyle_elements, 1):
                if bodystyle_element.is_displayed():
                    bodystyle_text = bodystyle_element.text.strip()
                    
                    if bodystyle_text and len(bodystyle_text) > 1:  # 过滤掉过短的文本
                        # 提取价格信息（查找父容器中的价格信息）
                        price_info = self.extract_bodystyle_price_info(bodystyle_element)
                        
                        bodystyle_option = {
                            'name': bodystyle_text,
                            'price': price_info if price_info else 'Standard',
                            'description': '',
                            'element': bodystyle_element
                        }
                        
                        bodystyle_options.append(bodystyle_option)
                        print(f"            ✓ 找到BodyStyle选项 {i}: {bodystyle_text}")
                        
                        if price_info:
                            print(f"              ✓ 价格信息: {price_info}")
            
            # 如果没找到，创建默认选项
            if not bodystyle_options:
                print(f"            ⚠️  未找到BodyStyle选项，使用默认值")
                bodystyle_options = [
                    {'name': '5-door Hatchback', 'price': 'Standard', 'description': 'Standard body style'},
                    {'name': 'Estate', 'price': '+£1,200', 'description': 'Estate body style'}
                ]
            
            print(f"          🎯 共提取到 {len(bodystyle_options)} 个真正的BodyStyle选项")
            return bodystyle_options
            
        except Exception as e:
            print(f"            ❌ 抓取Bodystyle选项时出错: {e}")
            return []
    
    def scrape_colour_data(self):
        """
        抓取Colour页面的数据，实现滚动抓取机制
        
        Returns:
            list: 颜色选项列表
        """
        print("    🌈 开始抓取Colour选项...")
        
        try:
            # 步骤1：导航到Colour页面
            if not self.navigate_to_colour_page():
                print("    ❌ 无法进入Colour页面")
                return []
            
            # 步骤2：等待Colour页面加载
            print("    ⏳ 等待Colour页面加载...")
            time.sleep(3)
            
            # 步骤3：实现滚动抓取频色选项
            colour_options = self.extract_colour_options_with_scrolling()
            
            if colour_options:
                print(f"    ✅ 成功抓取到 {len(colour_options)} 个颜色选项")
                for i, colour in enumerate(colour_options, 1):
                    print(f"      {i}. {colour.get('name', 'Unknown')} - {colour.get('price', 'N/A')}")
            else:
                print("    ⚠️  未找到颜色选项")
                # 使用默认颜色数据
                colour_options = [
                    {'name': 'Agate Black', 'price': 'Standard', 'description': 'Metallic'},
                    {'name': 'Blazer Blue', 'price': '+£595', 'description': 'Metallic'},
                    {'name': 'Ruby Red', 'price': '+£545', 'description': 'Metallic'}
                ]
            
            return colour_options
            
        except Exception as e:
            print(f"    ❌ Colour数据抓取出错: {e}")
            return []
    
    def navigate_to_colour_page(self):
        """
        导航到Colour配置页面
        
        Returns:
            bool: 是否成功进入Colour页面
        """
        print("    🧭 导航到Colour页面...")
        
        try:
            # 等待页面更新后再导航
            time.sleep(2)
            
            # 方法1：查找导航栏中的Colour按钮
            nav_state = self.get_navigation_state()
            if nav_state and 'Colour' in nav_state:
                colour_nav_info = nav_state['Colour']
                
                if (colour_nav_info.get('enabled', False) and 
                    colour_nav_info.get('aria_disabled', 'true') == 'false'):
                    
                    colour_button = self.find_navigation_button('Colour')
                    if colour_button:
                        print("      ✓ 找到Colour导航按钮")
                        self.click_element_safely(colour_button)
                        time.sleep(2)
                        
                        if self.verify_colour_page_loaded():
                            print("      ✅ 成功进入Colour页面")
                            return True
            
            # 方法2：查找Colour相关的直接链接
            colour_selectors = [
                'a[href*="colour"]',
                'a[href*="color"]',
                'button[data-testid*="colour"]',
                'button[data-testid*="color"]',
                '[class*="Colour"] button',
                '[class*="Color"] button',
                'button[aria-label*="colour" i]',
                'button[aria-label*="color" i]'
            ]
            
            for selector in colour_selectors:
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    for element in elements:
                        if element.is_displayed() and element.is_enabled():
                            print(f"      ✓ 找到Colour链接: {selector}")
                            self.click_element_safely(element)
                            time.sleep(2)
                            
                            if self.verify_colour_page_loaded():
                                print("      ✅ 通过直接链接进入Colour页面")
                                return True
                except Exception:
                    continue
            
            # 方法3：检查当前URL是否已经在Colour页面
            current_url = self.driver.current_url.lower()
            if 'colour' in current_url or 'color' in current_url:
                print("      ✓ 当前URL显示已在Colour页面")
                return self.verify_colour_page_loaded()
            
            print("      ❌ 所有Colour导航方法都失败")
            return False
            
        except Exception as e:
            print(f"      ❌ 导航到Colour页面时出错: {e}")
            return False
    
    def verify_colour_page_loaded(self):
        """
        验证Colour页面是否已加载
        
        Returns:
            bool: 是否已加载Colour页面
        """
        try:
            # 检查方法1：查找Colour相关的页面元素
            colour_indicators = [
                '[data-testid*="colour"]',
                '[data-testid*="color"]',
                '[class*="Colour"]',
                '[class*="Color"]',
                'h1, h2, h3[class*="colour" i]',
                'h1, h2, h3[class*="color" i]',
                'div[class*="ColourConfiguration"]',
                'div[class*="ColorConfiguration"]'
            ]
            
            for selector in colour_indicators:
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    if elements:
                        visible_elements = [el for el in elements if el.is_displayed()]
                        if visible_elements:
                            print(f"      ✓ 检测到Colour页面元素: {selector}")
                            return True
                except Exception:
                    continue
            
            # 检查方法2：URL验证
            current_url = self.driver.current_url.lower()
            if 'colour' in current_url or 'color' in current_url:
                print(f"      ✓ URL显示在Colour页面")
                return True
            
            # 检查方法3：导航状态
            nav_state = self.get_navigation_state()
            if nav_state and 'Colour' in nav_state:
                colour_info = nav_state['Colour']
                if colour_info.get('current', False):
                    print(f"      ✓ 导航状态显示在Colour页面")
                    return True
            
            return False
            
        except Exception as e:
            print(f"      验证Colour页面时出错: {e}")
            return False
        """
        提取BodyStyle元素的价格信息
        
        Args:
            bodystyle_element (WebElement): BodyStyle元素
            
        Returns:
            str or None: 价格信息
        """
        try:
            # 向上查找包含BodyStyle元素的产品瓦片容器
            container = None
            try:
                container = bodystyle_element.find_element(By.XPATH, './ancestor::div[contains(@class, "ProductTile")]')
            except Exception:
                try:
                    container = bodystyle_element.find_element(By.XPATH, './ancestor::div[contains(@data-cy, "")]')
                except Exception:
                    container = bodystyle_element.find_element(By.XPATH, './ancestor::div[position()<=3]')
            
            if container:
                # 在容器内查找价格信息
                price_selectors = [
                    '*[class*="Price"]',
                    '*[class*="price"]',
                    '*[class*="OTR"]',
                    '*[class*="Cost"]'
                ]
                
                for selector in price_selectors:
                    try:
                        price_elements = container.find_elements(By.CSS_SELECTOR, selector)
                        for price_elem in price_elements:
                            if price_elem.is_displayed():
                                price_text = price_elem.text.strip()
                                if price_text and ('£' in price_text or 'OTR' in price_text):
                                    return price_text
                    except Exception:
                        continue
                
                # 如果没找到专门的价格元素，在全部文本中搜索
                container_text = container.text
                lines = container_text.split('\n')
                for line in lines:
                    line = line.strip()
                    if line and ('£' in line or 'OTR' in line) and len(line) < 50:
                        return line
            
            return None
            
        except Exception as e:
            print(f"              提取价格信息时出错: {e}")
            return None
    
    def extract_bodystyle_option_data(self, element):
        """
        从Bodystyle选项元素中提取数据
        
        Args:
            element (WebElement): Bodystyle选项元素
            
        Returns:
            dict or None: Bodystyle选项数据
        """
        try:
            name = ''
            price = ''
            description = ''
            
            # 方法1：从data-cy属性获取名称
            data_cy = element.get_attribute('data-cy')
            if data_cy:
                name = data_cy
            
            # 方法2：从元素文本获取信息
            element_text = element.text.strip()
            if element_text:
                lines = element_text.split('\n')
                
                for line in lines:
                    line = line.strip()
                    if line:
                        # 识别价格
                        if '£' in line or '$' in line or '€' in line:
                            if not price:
                                price = line
                        # 识别名称
                        elif not name and len(line) > 2:
                            name = line
                        # 其他作为描述
                        elif not description and len(line) > 5:
                            description = line
            
            # 验证数据
            if name and len(name) > 1:
                return {
                    'name': name,
                    'price': price if price else 'Standard',
                    'description': description,
                    'element_text': element_text
                }
            
            return None
            
        except Exception as e:
            print(f"            提取Bodystyle选项数据时出错: {e}")
            return None
    
    def update_car_objects_with_bodystyle_data(self, car_series, target_model, all_bodystyle_data):
        """
        将Bodystyle数据更新到对应的CarObject中
        根据新的业务逻辑，每个model_name+drive组合是一个独立的CarObject
        
        Args:
            car_series (CarSeries): 车系对象
            target_model (str): 目标车型名称
            all_bodystyle_data (dict): 所有Drive选项对应的Bodystyle数据
        """
        print(f"    🔄 为 {target_model} 的每个CarObject添加Bodystyle数据...")
        
        try:
            updated_objects = 0
            total_bodystyles = 0
            
            # 遍历所有CarObject，找到匹配的车型
            for car_object in car_series.car_object_list:
                if car_object.model_name.lower() == target_model.lower():
                    drive_name = car_object.drive
                    
                    if drive_name and drive_name in all_bodystyle_data:
                        bodystyle_list = all_bodystyle_data[drive_name]
                        
                        print(f"      ✓ 为 {target_model} + {drive_name} 添加 {len(bodystyle_list)} 个Bodystyle选项")
                        
                        # 清空现有的body_styles
                        car_object.body_styles = []
                        
                        # 添加当前Drive对应的Bodystyle数据
                        for bodystyle_option in bodystyle_list:
                            bodystyle_name = bodystyle_option.get('name', '')
                            bodystyle_price = bodystyle_option.get('price', 'Standard')
                            bodystyle_description = bodystyle_option.get('description', '')
                            
                            if bodystyle_name:
                                car_object.add_bodystyle(
                                    bodystyle_name, 
                                    drive_name, 
                                    bodystyle_price, 
                                    bodystyle_description
                                )
                                total_bodystyles += 1
                        
                        updated_objects += 1
                    else:
                        print(f"      ⚠️  未找到 {drive_name} 对应的Bodystyle数据")
            
            print(f"    ✅ 共更新了 {updated_objects} 个CarObject，添加了 {total_bodystyles} 个Bodystyle选项")
            
        except Exception as e:
            print(f"    ❌ 更新Bodystyle数据时出错: {e}")
    
    def update_car_objects_with_drive_data(self, car_series, target_model, drive_data):
        """
        根据用户澄清的业务逻辑，为每个Drive创建一个新的CarObject
        唯一性规则：model_name + drive 组合是唯一值
        
        Args:
            car_series (CarSeries): 车系对象
            target_model (str): 目标车型名称
            drive_data (list): Drive数据列表
        """
        print(f"    🔄 为 {target_model} 的每个Drive创建独立的CarObject...")
        
        try:
            # 查找并移除现有的目标车型
            original_car_object = None
            for i, car_object in enumerate(car_series.car_object_list):
                if car_object.model_name.lower() == target_model.lower():
                    original_car_object = car_object
                    car_series.car_object_list.pop(i)
                    break
            
            if not original_car_object:
                print(f"    ⚠️  未找到车型 {target_model} 的原始 CarObject")
                return
            
            # 为每个Drive创建新的CarObject
            created_objects = 0
            for drive_option in drive_data:
                drive_name = drive_option.get('name', '')
                
                if drive_name:
                    # 创建新的CarObject，使用drive参数
                    new_car_object = CarObject(
                        series_name=original_car_object.series_name,
                        model_name=original_car_object.model_name,
                        price=original_car_object.price,
                        drive=drive_name  # 使用drive属性而不是drive_types
                    )
                    
                    # 复制其他属性
                    new_car_object.key_features = original_car_object.key_features.copy()
                    new_car_object.specifications = original_car_object.specifications.copy()
                    new_car_object.body_style = original_car_object.body_style
                    new_car_object.colors = original_car_object.colors.copy()
                    new_car_object.interiors = original_car_object.interiors.copy()
                    new_car_object.extras_list = original_car_object.extras_list.copy()
                    
                    # 添加到车系中
                    car_series.car_object_list.append(new_car_object)
                    created_objects += 1
                    
                    print(f"      ✓ 创建 CarObject: {target_model} + {drive_name}")
            
            print(f"    ✅ 成功为 {target_model} 创建了 {created_objects} 个独立的CarObject")
            
        except Exception as e:
            print(f"    ❌ 创建 Drive CarObject时出错: {e}")
    
    def scrape_drive_data(self):
        """
        抓取Drive页面的数据
        
        Returns:
            list: Drive选项列表，每个元素包含drive名称、价格等信息
        """
        print("    🔍 开始抓取Drive选项...")
        
        try:
            # 步骤1：检查是否已在Drive页面，如果不在则导航到Drive页面
            if not self.navigate_to_drive_page():
                print("    ❌ 无法进入Drive页面")
                return []
            
            # 步骤2：等待Drive页面完全加载
            print("    ⏳ 等待Drive页面加载...")
            time.sleep(3)
            
            # 步骤3：抓取所有可用的Drive选项
            drive_options = self.extract_drive_options()
            
            if drive_options:
                print(f"    ✅ 成功抓取到 {len(drive_options)} 个Drive选项")
                for i, drive in enumerate(drive_options, 1):
                    print(f"      {i}. {drive.get('name', 'Unknown')} - {drive.get('price', 'N/A')}")
            else:
                print("    ⚠️  未找到Drive选项")
            
            return drive_options
            
        except Exception as e:
            print(f"    ❌ Drive数据抓取出错: {e}")
            return []
    
    def navigate_to_drive_page(self):
        """
        导航到Drive配置页面
        
        Returns:
            bool: 是否成功进入Drive页面
        """
        print("    🧭 导航到Drive页面...")
        
        try:
            # 方法1：检查导航栏中的Drive按钮
            nav_state = self.get_navigation_state()
            if nav_state and 'Drive' in nav_state:
                drive_nav_info = nav_state['Drive']
                
                if (drive_nav_info.get('enabled', False) and 
                    drive_nav_info.get('aria_disabled', 'true') == 'false'):
                    
                    # 点击Drive导航按钮
                    drive_button = self.find_navigation_button('Drive')
                    if drive_button:
                        print("      ✓ 找到Drive导航按钮")
                        self.click_element_safely(drive_button)
                        time.sleep(2)
                        
                        # 验证是否成功进入Drive页面
                        if self.verify_drive_page_loaded():
                            print("      ✅ 成功进入Drive页面")
                            return True
            
            # 方法2：查找Drive相关的直接链接或按钮
            drive_selectors = [
                'a[href*="drive"]',
                'button[data-testid*="drive"]',
                '[class*="Drive"] button',
                'button[aria-label*="drive" i]'
            ]
            
            for selector in drive_selectors:
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    for element in elements:
                        if element.is_displayed() and element.is_enabled():
                            print(f"      ✓ 找到Drive链接: {selector}")
                            self.click_element_safely(element)
                            time.sleep(2)
                            
                            if self.verify_drive_page_loaded():
                                print("      ✅ 通过直接链接进入Drive页面")
                                return True
                except Exception:
                    continue
            
            # 方法3：检查当前URL是否已经包含drive相关内容
            current_url = self.driver.current_url.lower()
            if 'drive' in current_url:
                print("      ✓ 当前URL显示已在Drive页面")
                return self.verify_drive_page_loaded()
            
            print("      ❌ 所有导航方法都失败")
            return False
            
        except Exception as e:
            print(f"      ❌ 导航到Drive页面时出错: {e}")
            return False
    
    def find_navigation_button(self, nav_text):
        """
        查找导航栏中的指定按钮
        
        Args:
            nav_text (str): 导航按钮文本
            
        Returns:
            WebElement or None: 找到的导航按钮
        """
        try:
            # 查找导航容器
            nav_container = self.driver.find_element(By.CSS_SELECTOR, 'nav[data-testid="Navigation_Container"]')
            
            # 在导航容器中查找指定文本的按钮
            nav_buttons = nav_container.find_elements(By.CSS_SELECTOR, 'button, a')
            
            for button in nav_buttons:
                if button.is_displayed():
                    button_text = button.text.strip()
                    if button_text.lower() == nav_text.lower():
                        return button
            
            return None
            
        except Exception as e:
            print(f"      查找导航按钮失败: {e}")
            return None
    
    def verify_drive_page_loaded(self):
        """
        验证Drive页面是否已加载
        
        Returns:
            bool: 是否已加载Drive页面
        """
        try:
            # 检查方法1：查找Drive相关的页面元素
            drive_indicators = [
                '[data-testid*="drive"]',
                '[class*="Drive"]',
                '[class*="drivetrain"]',
                'h1, h2, h3[class*="drive" i]',
                'div[class*="DriveConfiguration"]'
            ]
            
            for selector in drive_indicators:
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    if elements:
                        visible_elements = [el for el in elements if el.is_displayed()]
                        if visible_elements:
                            print(f"      ✓ 检测到Drive页面元素: {selector}")
                            return True
                except Exception:
                    continue
            
            # 检查方法2：URL验证
            current_url = self.driver.current_url.lower()
            if 'drive' in current_url:
                print(f"      ✓ URL显示在Drive页面")
                return True
            
            # 检查方法3：导航状态
            nav_state = self.get_navigation_state()
            if nav_state and 'Drive' in nav_state:
                drive_info = nav_state['Drive']
                if drive_info.get('current', False):
                    print(f"      ✓ 导航状态显示在Drive页面")
                    return True
            
            return False
            
        except Exception as e:
            print(f"      验证Drive页面时出错: {e}")
            return False
    
    def extract_drive_options(self):
        """
        从Drive页面提取所有可用的Drive选项
        只识别 ProductTileSection__ProductTileMainValue 标签内的内容作为Drive
        
        Returns:
            list: Drive选项列表
        """
        print("    🔍 提取Drive选项...")
        
        drive_options = []
        
        try:
            # 等待页面稳定
            time.sleep(2)
            
            # 根据用户澄清的业务逻辑：只有ProductTileMainValue标签内的内容才是Drive
            drive_main_value_selector = 'span.ProductTileSection__ProductTileMainValue-sc-5noent-16'
            
            # 查找所有Drive主值元素
            drive_main_elements = self.driver.find_elements(By.CSS_SELECTOR, drive_main_value_selector)
            
            print(f"      🔍 找到 {len(drive_main_elements)} 个ProductTileMainValue元素")
            
            for i, drive_element in enumerate(drive_main_elements, 1):
                if drive_element.is_displayed():
                    drive_text = drive_element.text.strip()
                    
                    if drive_text and len(drive_text) > 10:  # 过滤掉过短的文本
                        # 查找同一个容器内的Selected按钮
                        selected_button = self.find_selected_button_for_drive(drive_element)
                        
                        drive_option = {
                            'name': drive_text,
                            'price': 'Standard',
                            'description': '',
                            'element': drive_element,
                            'selected_button': selected_button
                        }
                        
                        drive_options.append(drive_option)
                        print(f"      ✓ 找到Drive选项 {i}: {drive_text}")
                        
                        if selected_button:
                            print(f"        ✓ 找到对应的Selected按钮")
                        else:
                            print(f"        ⚠️  未找到对应的Selected按钮")
            
            print(f"  🎯 共提取到 {len(drive_options)} 个真正的Drive选项")
            return drive_options
            
        except Exception as e:
            print(f"    ❌ 提取Drive选项时出错: {e}")
            return []
    
    def find_selected_button_for_drive(self, drive_element):
        """
        查找与Drive元素在同一个DIV容器内的Selected按钮
        
        Args:
            drive_element (WebElement): Drive元素
            
        Returns:
            WebElement or None: 找到的Selected按钮
        """
        try:
            # 向上查找包含Drive元素的产品瓦片容器
            container_selectors = [
                'div[class*="ProductTile"]',
                'div[data-cy]',
                'div[class*="Product"]'
            ]
            
            container = None
            for selector in container_selectors:
                try:
                    container = drive_element.find_element(By.XPATH, f'./ancestor::{selector.split("[" if "[" in selector else " ")[0]}')
                    if container:
                        break
                except Exception:
                    continue
            
            if not container:
                # 使用通用父容器查找
                container = drive_element.find_element(By.XPATH, './ancestor::div[contains(@class, "Product") or contains(@data-cy, "")]')
            
            if container:
                # 在容器内查找Selected按钮
                selected_button_selectors = [
                    'button[class*="Selected"]',
                    'button:contains("Selected")',
                    'button[aria-label*="Selected"]',
                    '*[class*="Selected"]',
                    'button'
                ]
                
                for selector in selected_button_selectors:
                    try:
                        if 'contains' in selector:
                            # 使用XPath查找包含文本的按钮
                            buttons = container.find_elements(By.XPATH, './/button[contains(text(), "Selected")]')
                        else:
                            buttons = container.find_elements(By.CSS_SELECTOR, selector)
                        
                        for button in buttons:
                            if button.is_displayed() and button.is_enabled():
                                button_text = button.text.strip().lower()
                                if 'selected' in button_text:
                                    return button
                    except Exception:
                        continue
            
            return None
            
        except Exception as e:
            print(f"        查找Selected按钮时出错: {e}")
            return None
    
    def extract_drive_option_data(self, element):
        """
        从Drive选项元素中提取数据
        
        Args:
            element (WebElement): Drive选项元素
            
        Returns:
            dict or None: Drive选项数据
        """
        try:
            # 提取名称
            name = ''
            price = ''
            description = ''
            
            # 方法1：从data-cy属性获取名称
            data_cy = element.get_attribute('data-cy')
            if data_cy:
                name = data_cy
            
            # 方法2：从元素文本获取信息
            element_text = element.text.strip()
            if element_text:
                lines = element_text.split('\n')
                
                for line in lines:
                    line = line.strip()
                    if line:
                        # 识别价格（包含£或货币符号）
                        if '£' in line or '$' in line or '€' in line:
                            if not price:
                                price = line
                        # 识别名称（第一个非价格行）
                        elif not name and len(line) > 2:
                            name = line
                        # 其他作为描述
                        elif not description and len(line) > 5:
                            description = line
            
            # 方法3：查找子元素
            if not name or not price:
                try:
                    # 查找标题元素
                    title_selectors = [
                        'h1, h2, h3, h4, h5, h6',
                        '[class*="title"]',
                        '[class*="name"]',
                        'strong',
                        '.text-lg, .text-xl'
                    ]
                    
                    for selector in title_selectors:
                        title_elements = element.find_elements(By.CSS_SELECTOR, selector)
                        for title_elem in title_elements:
                            if title_elem.is_displayed():
                                title_text = title_elem.text.strip()
                                if title_text and not name:
                                    name = title_text
                                    break
                        if name:
                            break
                    
                    # 查找价格元素
                    price_selectors = [
                        '[class*="price"]',
                        '[class*="cost"]',
                        '[class*="amount"]'
                    ]
                    
                    for selector in price_selectors:
                        price_elements = element.find_elements(By.CSS_SELECTOR, selector)
                        for price_elem in price_elements:
                            if price_elem.is_displayed():
                                price_text = price_elem.text.strip()
                                if price_text and not price:
                                    price = price_text
                                    break
                        if price:
                            break
                            
                except Exception:
                    pass
            
            # 验证数据
            if name and len(name) > 1:
                return {
                    'name': name,
                    'price': price if price else 'Standard',
                    'description': description,
                    'element_text': element_text
                }
            
            return None
            
        except Exception as e:
            print(f"      提取Drive选项数据时出错: {e}")
            return None
    
    def wait_for_page_load(self):
        """等待页面关键元素加载完成 - 集成渐进式等待策略"""
        print("📋 页面加载检查...")
        
        try:
            # 第一阶段：等待页面主容器加载
            print("  ⚙️  等待页面主容器...")
            self.wait.until(EC.presence_of_element_located(
                (By.CSS_SELECTOR, '.aem-page')
            ))
            print("    ✅ 页面主容器加载完成")
            
            # 第二阶段：渐进式内容检查（基于成功经验）
            print("  🔍 渐进式内容加载检查...")
            max_wait = 12  # 少于稳定版的 15秒
            check_interval = 3
            
            content_loaded = False
            for i in range(0, max_wait, check_interval):
                time.sleep(check_interval)
                
                try:
                    # 检查页面内容是否已加载
                    body_text = self.driver.find_element(By.TAG_NAME, "body").text
                    if len(body_text) > 1000:
                        print(f"    ✅ 页面内容已加载 (第 {i+check_interval} 秒)")
                        content_loaded = True
                        break
                except Exception:
                    continue
            
            if not content_loaded:
                print("    ⚠️  内容加载检查超时，继续执行")
            
            # 第三阶段：检查车型轮播组件
            print("  🎠 检查车型轮播组件...")
            carousel_elements = self.driver.find_elements(
                By.CSS_SELECTOR, 'div[data-cy][class*="ProductTile"]'
            )
            
            if carousel_elements:
                print(f"    ✅ 检测到 {len(carousel_elements)} 个车型元素")
            else:
                print("    ⚠️  未检测到车型元素，页面可能未完全加载")
                
                # 尝试替代选择器
                alternative_selectors = [
                    'div[data-cy]',
                    '[class*="ProductTile"]',
                    '[class*="ProductSection"]'
                ]
                
                for alt_selector in alternative_selectors:
                    alt_elements = self.driver.find_elements(By.CSS_SELECTOR, alt_selector)
                    if alt_elements:
                        print(f"    ℹ️  使用替代选择器 '{alt_selector}' 找到 {len(alt_elements)} 个元素")
                        break
            
            # 第四阶段：检查导航容器（为后续配置流程做准备）
            try:
                nav_container = self.driver.find_element(By.CSS_SELECTOR, 'nav[data-testid="Navigation_Container"]')
                print("    ✅ 检测到导航容器，为配置流程做好准备")
            except Exception:
                print("    ⚠️  未检测到导航容器")
            
            print("✅ 页面加载检查完成")
            
        except TimeoutException:
            print("⚠️  页面加载超时，尝试继续执行...")
        except Exception as e:
            print(f"❌ 页面加载检查时出错: {e}")
            
        except TimeoutException:
            print("警告：页面加载超时，尝试继续执行...")
        except Exception as e:
            print(f"页面加载检查时出错: {e}")
    
    def handle_cookie_consent(self):
        """处理cookie同意弹窗 - 使用稳定版分析器验证的策略"""
        print("🍪 开始增强Cookie处理...")
        
        try:
            # 渐进式等待页面稳定（基于成功测试经验）
            self.progressive_page_wait()
            
            # 方法1: 处理福特特定的Cookie弹窗
            ford_success = self.handle_ford_specific_cookies()
            
            # 方法2: 通用Cookie处理
            generic_success = self.handle_generic_cookies()
            
            # 方法3: JavaScript强制清理
            cleanup_success = self.force_cleanup_cookie_elements()
            
            # 方法4: 验证页面交互性
            interactive = self.verify_page_interactivity()
            
            overall_success = ford_success or generic_success or cleanup_success or interactive
            
            if overall_success:
                print("✅ Cookie处理完成")
            else:
                print("⚠️  Cookie处理未完全成功，但继续执行")
                
        except Exception as e:
            print(f"❌ Cookie处理过程出错: {e}")
            print("继续执行程序...")
    
    def progressive_page_wait(self):
        """渐进式页面等待机制 - 基于稳定版测试经验"""
        print("  ⏱️  渐进式页面加载检查...")
        
        max_wait = 15  # 最大等待15秒
        check_interval = 3
        
        for i in range(0, max_wait, check_interval):
            time.sleep(check_interval)
            
            try:
                # 检查页面内容是否已加载
                body_text = self.driver.find_element(By.TAG_NAME, "body").text
                if len(body_text) > 1000:
                    print(f"    ✅ 页面内容已加载 (第 {i+check_interval} 秒)")
                    break
            except Exception:
                continue
    
    def handle_ford_specific_cookies(self):
        """处理福特特定的Cookie弹窗 - 基于深度分析发现的CSS类"""
        print("  🎯 处理福特特定Cookie...")
        
        # 基于深度分析发现的福特网站Cookie类
        ford_selectors = [
            '.styles__CookieDisclaimerWrapper-sc-dx4a8y-0.bByYil',
            '.styles__CookieDisclaimerContent-sc-dx4a8y-3.hUJXDq',
            '[class*="styles__CookieDisclaimer"]',
            'div[role="dialog"][class*="Cookie"]'
        ]
        
        found_elements = []
        for selector in ford_selectors:
            try:
                elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                for element in elements:
                    if element.is_displayed():
                        found_elements.append(element)
                        print(f"    ✓ 发现福特Cookie元素: {selector}")
            except Exception:
                continue
        
        if found_elements:
            # 尝试在这些容器内找同意按钮
            for container in found_elements:
                try:
                    buttons = container.find_elements(By.TAG_NAME, 'button')
                    for button in buttons:
                        if self.is_consent_button(button):
                            self.click_element_safely(button)
                            print(f"    ✅ 点击了福特Cookie同意按钮")
                            time.sleep(2)
                            return True
                except Exception:
                    continue
            
            # 如果找不到按钮，直接移除容器
            for element in found_elements:
                try:
                    self.driver.execute_script("arguments[0].remove();", element)
                    print(f"    🗑️  移除了福特Cookie容器")
                except Exception:
                    continue
            return True
        
        return False
    
    def handle_generic_cookies(self):
        """处理通用Cookie弹窗"""
        print("  🌐 处理通用Cookie...")
        
        generic_selectors = [
            'button[data-testid*="accept"]',
            'button[id*="accept"]',
            'button[class*="accept"]',
            'button[aria-label*="accept" i]',
            '[role="dialog"] button',
            '.cookie-accept',
            '#cookie-accept',
            'button'
        ]
        
        for selector in generic_selectors:
            try:
                buttons = self.driver.find_elements(By.CSS_SELECTOR, selector)
                for button in buttons:
                    if self.is_consent_button(button):
                        self.click_element_safely(button)
                        print(f"    ✅ 点击了通用Cookie同意按钮")
                        time.sleep(2)
                        return True
            except Exception:
                continue
        
        return False
    
    def force_cleanup_cookie_elements(self):
        """JavaScript强制清理Cookie元素 - 基于稳定版成功经验"""
        print("  🧹 JavaScript强制清理Cookie元素...")
        
        try:
            cleanup_script = """
            var removedCount = 0;
            
            // 福特特定的Cookie选择器
            var fordSelectors = [
                '.styles__CookieDisclaimerWrapper-sc-dx4a8y-0',
                '.styles__CookieDisclaimerContent-sc-dx4a8y-3',
                '[class*="styles__CookieDisclaimer"]',
                '[class*="CookieDisclaimer"]'
            ];
            
            // 通用Cookie选择器
            var genericSelectors = [
                '[class*="cookie"]',
                '[class*="Cookie"]',
                '[class*="consent"]',
                '[id*="cookie"]',
                '[role="dialog"]',
                '[class*="modal"]',
                '[class*="overlay"]',
                '[class*="backdrop"]'
            ];
            
            // 处理福特特定选择器
            fordSelectors.forEach(function(selector) {
                try {
                    var elements = document.querySelectorAll(selector);
                    elements.forEach(function(el) {
                        if (el && el.offsetParent !== null) {
                            el.style.display = 'none';
                            el.remove();
                            removedCount++;
                        }
                    });
                } catch(e) {}
            });
            
            // 处理通用选择器（更保守）
            genericSelectors.forEach(function(selector) {
                try {
                    var elements = document.querySelectorAll(selector);
                    elements.forEach(function(el) {
                        if (el && el.offsetParent !== null) {
                            var rect = el.getBoundingClientRect();
                            // 只移除大的overlay元素
                            if (rect.width > 200 && rect.height > 100) {
                                var zIndex = window.getComputedStyle(el).zIndex;
                                if (zIndex && parseInt(zIndex) > 100) {
                                    el.style.display = 'none';
                                    el.remove();
                                    removedCount++;
                                }
                            }
                        }
                    });
                } catch(e) {}
            });
            
            // 重置页面样式
            document.body.style.overflow = 'auto';
            document.documentElement.style.overflow = 'auto';
            
            return removedCount;
            """
            
            removed_count = self.driver.execute_script(cleanup_script)
            if removed_count > 0:
                print(f"    🗑️  移除了 {removed_count} 个Cookie相关元素")
                return True
            
        except Exception as e:
            print(f"    ❌ JavaScript清理失败: {e}")
        
        return False
    
    def is_consent_button(self, button):
        """判断是否是同意按钮"""
        try:
            if not button.is_displayed() or not button.is_enabled():
                return False
            
            button_text = button.text.strip().lower()
            button_class = (button.get_attribute('class') or '').lower()
            button_aria_label = (button.get_attribute('aria-label') or '').lower()
            
            # 同意关键词
            consent_keywords = [
                'accept', 'agree', 'allow', 'ok', 'continue', 
                'consent', 'yes', 'i agree', 'accept all'
            ]
            
            # 拒绝关键词（要避免）
            reject_keywords = [
                'reject', 'decline', 'refuse', 'deny', 'no',
                'manage', 'settings', 'preferences', 'customize'
            ]
            
            has_consent = any(keyword in button_text or keyword in button_class or keyword in button_aria_label 
                            for keyword in consent_keywords)
            has_reject = any(keyword in button_text or keyword in button_class or keyword in button_aria_label 
                           for keyword in reject_keywords)
            
            return has_consent and not has_reject
            
        except Exception:
            return False
    
    def click_element_safely(self, element):
        """安全地点击元素"""
        try:
            # 滚动到元素
            self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", element)
            time.sleep(0.5)
            
            # 尝试普通点击
            try:
                element.click()
            except ElementClickInterceptedException:
                # 使用JavaScript点击
                self.driver.execute_script("arguments[0].click();", element)
                
        except Exception as e:
            # 最后尝试：强制JavaScript点击
            try:
                self.driver.execute_script("arguments[0].click();", element)
            except Exception:
                raise e
    
    def verify_page_interactivity(self):
        """验证页面是否可交互 - 基于稳定版测试经验"""
        print("  🔍 验证页面交互性...")
        
        try:
            # 查找车型元素并检查是否可点击
            model_elements = self.driver.find_elements(By.CSS_SELECTOR, 'div[data-cy][class*="ProductTile"]')
            
            clickable_models = 0
            for model in model_elements[:3]:  # 只检查前3个
                data_cy = model.get_attribute('data-cy')
                if data_cy and data_cy not in ['header-selling-price', 'sticky-bar']:
                    try:
                        # 检查元素是否在视口内且可点击
                        rect = self.driver.execute_script("""
                            var rect = arguments[0].getBoundingClientRect();
                            return {
                                x: rect.x,
                                y: rect.y,
                                width: rect.width,
                                height: rect.height,
                                visible: rect.width > 0 && rect.height > 0
                            };
                        """, model)
                        
                        if rect['visible']:
                            clickable_models += 1
                            
                    except Exception:
                        continue
            
            print(f"    ✓ 发现 {clickable_models} 个可交互的车型元素")
            return clickable_models > 0
            
        except Exception as e:
            print(f"    ❌ 验证交互性失败: {e}")
            return False
    
    def select_model_and_enter_configuration(self, target_model_name):
        """
        选择指定的车型并进入配置流程
        
        Args:
            target_model_name (str): 目标车型名称（如 "Titanium", "ST-Line" 等）
            
        Returns:
            bool: 是否成功进入配置流程
        """
        print(f"🎯 开始选择车型: {target_model_name}")
        
        try:
            # 第一步：确保页面已加载并处理了Cookie
            print("  🔄 确保页面状态...")
            time.sleep(3)  # 增加等待时间
            
            # 预先清理阻挡元素
            self.force_cleanup_blocking_elements()
            
            # 第二步：查找目标车型元素
            target_element = self.find_model_element(target_model_name)
            if not target_element:
                print(f"  ❌ 未找到车型: {target_model_name}")
                return False
            
            # 第三步：尝试点击车型进入配置流程
            success = self.click_model_to_configure(target_element, target_model_name)
            if not success:
                print(f"  ❌ 车型点击失败: {target_model_name}")
                return False
            
            # 第四步：验证是否成功进入配置流程
            if self.verify_configuration_entry():
                print(f"  ✅ 成功进入 {target_model_name} 的配置流程")
                return True
            else:
                print(f"  ⚠️  车型点击了但未进入配置流程")
                
                # 尝试等待更长时间后再次验证
                print("  ⏳ 等待额外时间后再次验证...")
                time.sleep(5)
                if self.verify_configuration_entry():
                    print(f"  ✅ 延迟验证成功，已进入 {target_model_name} 配置流程")
                    return True
                else:
                    return False
            
        except Exception as e:
            print(f"  ❌ 车型选择过程出错: {e}")
            return False
    
    def find_model_element(self, target_model_name):
        """
        查找指定名称的车型元素
        
        Args:
            target_model_name (str): 目标车型名称
            
        Returns:
            WebElement or None: 找到的车型元素
        """
        print(f"  🔍 查找车型元素: {target_model_name}")
        
        try:
            # 查找所有车型元素
            model_selectors = [
                f'div[data-cy="{target_model_name}"]',  # 精确匹配
                f'div[data-cy*="{target_model_name.lower()}"]',  # 包含匹配（小写）
                'div[data-cy][class*="ProductTile"]'  # 所有车型元素
            ]
            
            # 优先尝试精确匹配
            for i, selector in enumerate(model_selectors):
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    
                    if i < 2:  # 精确匹配或包含匹配
                        for element in elements:
                            if element.is_displayed():
                                data_cy = element.get_attribute('data-cy')
                                if data_cy and (data_cy == target_model_name or 
                                              target_model_name.lower() in data_cy.lower()):
                                    print(f"    ✅ 精确找到车型: {data_cy}")
                                    return element
                    else:  # 所有元素中搜索
                        for element in elements:
                            if element.is_displayed():
                                data_cy = element.get_attribute('data-cy')
                                element_text = element.text.strip()
                                
                                # 检查data-cy属性或元素文本
                                if ((data_cy and target_model_name.lower() in data_cy.lower()) or
                                    (element_text and target_model_name.lower() in element_text.lower())):
                                    print(f"    ✅ 通过文本找到车型: {data_cy or element_text[:30]}")
                                    return element
                                    
                except Exception as e:
                    print(f"    ⚠️  选择器 '{selector}' 失败: {e}")
                    continue
            
            # 如果还没找到，尝试滚动查找
            print(f"    🔄 在当前页面未找到 {target_model_name}，尝试滚动查找...")
            return self.find_model_with_scrolling(target_model_name)
            
        except Exception as e:
            print(f"    ❌ 查找车型元素时出错: {e}")
            return None
    
    def find_model_with_scrolling(self, target_model_name, max_scroll_attempts=5):
        """
        通过滚动轮播查找车型
        
        Args:
            target_model_name (str): 目标车型名称
            max_scroll_attempts (int): 最大滚动尝试次数
            
        Returns:
            WebElement or None: 找到的车型元素
        """
        print(f"    🎠 滚动查找车型: {target_model_name}")
        
        # 先重置到第一页
        self.reset_carousel_to_first_page()
        
        for attempt in range(max_scroll_attempts):
            print(f"      尝试 {attempt + 1}/{max_scroll_attempts}")
            
            # 在当前页面查找
            try:
                elements = self.driver.find_elements(By.CSS_SELECTOR, 'div[data-cy][class*="ProductTile"]')
                for element in elements:
                    if element.is_displayed():
                        data_cy = element.get_attribute('data-cy')
                        if data_cy and target_model_name.lower() in data_cy.lower():
                            print(f"      ✅ 滚动中找到车型: {data_cy}")
                            return element
            except Exception:
                pass
            
            # 如果没找到，尝试滚动到下一页
            if attempt < max_scroll_attempts - 1:
                if not self.scroll_carousel():
                    print(f"      ⚠️  无法继续滚动")
                    break
                time.sleep(2)
        
        print(f"    ❌ 滚动完成，未找到车型: {target_model_name}")
        return None
    
    def click_model_to_configure(self, element, model_name):
        """
        点击车型元素进入配置流程
        
        Args:
            element (WebElement): 车型元素
            model_name (str): 车型名称
            
        Returns:
            bool: 是否点击成功
        """
        print(f"  💱 点击车型进入配置: {model_name}")
        
        try:
            # 获取点击前的URL和导航状态
            before_url = self.driver.current_url
            before_nav_state = self.get_navigation_state()
            
            # 策略1：先尝试查找并点击车型内的特定按钮
            print("    🔍 查找车型内的配置按钮...")
            config_button_found = self.click_model_configuration_button(element, model_name)
            
            if config_button_found:
                time.sleep(3)
                after_url = self.driver.current_url
                after_nav_state = self.get_navigation_state()
                
                if (after_url != before_url or after_nav_state != before_nav_state):
                    print(f"    ✅ 配置按钮点击成功，页面发生变化")
                    return True
            
            # 策略2：如果找不到特定按钮，尝试点击整个车型元素
            print("    🔄 尝试点击整个车型元素...")
            success = self.click_element_with_multiple_strategies(element, model_name)
            
            if success:
                time.sleep(3)
                after_url = self.driver.current_url
                after_nav_state = self.get_navigation_state()
                
                if (after_url != before_url or after_nav_state != before_nav_state):
                    print(f"    ✅ 车型元素点击成功，页面发生变化")
                    return True
            
            print(f"    ❌ 所有点击策略都失败")
            return False
            
        except Exception as e:
            print(f"    ❌ 点击车型元素时出错: {e}")
            return False
    
    def click_model_configuration_button(self, model_element, model_name):
        """
        查找并点击车型内的配置按钮
        
        Args:
            model_element (WebElement): 车型元素
            model_name (str): 车型名称
            
        Returns:
            bool: 是否找到并成功点击配置按钮
        """
        try:
            # 常见的配置按钮选择器
            config_button_selectors = [
                'button[data-cy="select-btn"]',
                'button[class*="select"]',
                'button[class*="Select"]',
                'button[class*="configure"]',
                'button[class*="Configure"]',
                'button[aria-label*="select" i]',
                'button[aria-label*="configure" i]',
                'a[class*="select"]',
                'a[class*="configure"]',
                '.select-button',
                '.configure-button',
                'button',  # 最后尝试所有按钮
            ]
            
            for selector in config_button_selectors:
                try:
                    buttons = model_element.find_elements(By.CSS_SELECTOR, selector)
                    for button in buttons:
                        if button.is_displayed() and button.is_enabled():
                            button_text = button.text.strip().lower()
                            aria_label = (button.get_attribute('aria-label') or '').lower()
                            
                            # 检查是否是配置相关按钮
                            config_keywords = ['select', 'configure', 'build', 'customize', 'choose']
                            if (any(keyword in button_text for keyword in config_keywords) or
                                any(keyword in aria_label for keyword in config_keywords) or
                                selector in ['button[data-cy="select-btn"]']):
                                
                                print(f"      ✓ 找到配置按钮: '{button_text}' (selector: {selector})")
                                
                                # 尝试点击按钮
                                try:
                                    self.click_element_safely(button)
                                    print(f"      ✅ 成功点击配置按钮")
                                    return True
                                except Exception as click_error:
                                    print(f"      ⚠️  点击配置按钮失败: {click_error}")
                                    continue
                                    
                except Exception:
                    continue
            
            print(f"      ⚠️  未在车型 {model_name} 中找到配置按钮")
            return False
            
        except Exception as e:
            print(f"      查找配置按钮时出错: {e}")
            return False
    
    def click_element_with_multiple_strategies(self, element, model_name):
        """
        使用多种策略点击元素
        
        Args:
            element (WebElement): 要点击的元素
            model_name (str): 车型名称
            
        Returns:
            bool: 是否成功点击
        """
        try:
            # 首先清除可能的阻挡元素
            print("      🧡 清除可能的阻挡元素...")
            self.force_cleanup_blocking_elements()
            time.sleep(1)
            
            # 滚动到元素可见
            print("      🌀 滚动到元素位置...")
            self.driver.execute_script("arguments[0].scrollIntoView({block: 'center', behavior: 'smooth'});", element)
            time.sleep(2)  # 增加等待时间
            
            # 策略1：普通点击
            print("      🕸️  尝试普通点击...")
            try:
                element.click()
                print("      ✅ 普通点击成功")
                return True
            except ElementClickInterceptedException as e:
                print(f"      ⚠️  普通点击被阻挡: {e}")
            except Exception as e:
                print(f"      ⚠️  普通点击失败: {e}")
            
            # 策略2：JavaScript点击
            print("      💻 尝试JavaScript点击...")
            try:
                self.driver.execute_script("arguments[0].click();", element)
                print("      ✅ JavaScript点击成功")
                return True
            except Exception as e:
                print(f"      ⚠️  JavaScript点击失败: {e}")
            
            # 策略3：强制JavaScript点击（多种方式）
            print("      ⚡ 尝试强制JavaScript点击...")
            force_click_scripts = [
                "arguments[0].click();",  # 简单点击
                "arguments[0].dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true}));",  # 模拟鼠标事件
                "var event = new Event('click'); arguments[0].dispatchEvent(event);",  # 触发点击事件
                "arguments[0].focus(); arguments[0].click();",  # 先聚焦再点击
            ]
            
            for i, script in enumerate(force_click_scripts, 1):
                try:
                    self.driver.execute_script(script, element)
                    print(f"      ✅ 强制点击方法{i}成功")
                    return True
                except Exception as e:
                    print(f"      ⚠️  强制点击方法{i}失败: {e}")
                    continue
            
            # 策略4：尝试点击元素的父元素或子元素
            print("      📋 尝试点击相关元素...")
            try:
                # 尝试点击父元素
                parent = element.find_element(By.XPATH, '..')
                self.driver.execute_script("arguments[0].click();", parent)
                print("      ✅ 父元素点击成功")
                return True
            except Exception:
                pass
            
            try:
                # 尝试点击第一个子元素
                first_child = element.find_element(By.XPATH, './*')
                self.driver.execute_script("arguments[0].click();", first_child)
                print("      ✅ 子元素点击成功")
                return True
            except Exception:
                pass
            
            print(f"      ❌ 所有点击策略对{model_name}都失败")
            return False
            
        except Exception as e:
            print(f"      ❌ 多策略点击时出错: {e}")
            return False
    
    def force_cleanup_blocking_elements(self):
        """
        强制清理可能阻挡点击的元素
        """
        try:
            cleanup_script = """
            // 移除可能阻挡点击的overlay和模态框
            var overlays = document.querySelectorAll('[class*="overlay"], [class*="modal"], [class*="backdrop"], [style*="position: fixed"], [style*="z-index"]');
            var removedCount = 0;
            
            overlays.forEach(function(el) {
                var style = window.getComputedStyle(el);
                var zIndex = parseInt(style.zIndex);
                
                if (zIndex > 1000 || style.position === 'fixed') {
                    el.style.display = 'none';
                    el.style.visibility = 'hidden';
                    el.style.pointerEvents = 'none';
                    removedCount++;
                }
            });
            
            // 恢复页面交互
            document.body.style.overflow = 'auto';
            document.body.style.pointerEvents = 'auto';
            
            return removedCount;
            """
            
            removed = self.driver.execute_script(cleanup_script)
            if removed > 0:
                print(f"        ✓ 清理了 {removed} 个可能的阻挡元素")
            
        except Exception as e:
            print(f"        清理阻挡元素时出错: {e}")
    
    def get_navigation_state(self):
        """
        获取当前导航状态
        
        Returns:
            dict: 导航状态信息，每个导航项包含enabled、aria_disabled、current等状态
        """
        try:
            # 查找导航容器
            nav_container = self.driver.find_element(By.CSS_SELECTOR, 'nav[data-testid="Navigation_Container"]')
            nav_items = nav_container.find_elements(By.CSS_SELECTOR, 'button, a')
            
            nav_state = {}
            for item in nav_items:
                if item.is_displayed():
                    text = item.text.strip()
                    if text and len(text) < 20:
                        item_class = item.get_attribute('class') or ''
                        aria_disabled = item.get_attribute('aria-disabled')
                        
                        # 检测是否为当前激活的导航项（基于分析发现的CSS类）
                        is_current = 'cwAUaO' in item_class or 'active' in item_class.lower()
                        
                        nav_state[text] = {
                            'enabled': item.is_enabled(),
                            'aria_disabled': aria_disabled,
                            'class': item_class,
                            'current': is_current
                        }
            
            return nav_state
        except Exception as e:
            print(f"获取导航状态失败: {e}")
            return {}
    
    def verify_configuration_entry(self):
        """
        验证是否成功进入配置流程
        
        Returns:
            bool: 是否成功进入配置流程
        """
        print(f"  🔍 验证配置流程入口...")
        
        try:
            time.sleep(2)  # 等待页面响应
            
            # 检查方法1：导航状态变化检查
            nav_state = self.get_navigation_state()
            if nav_state:
                print("    🧭 检查导航状态...")
                
                # 检查Drive步骤是否可用或已激活
                drive_info = nav_state.get('Drive', {})
                if drive_info:
                    is_enabled = drive_info.get('enabled', False)
                    is_current = drive_info.get('current', False)
                    aria_disabled = drive_info.get('aria_disabled', 'true')
                    
                    print(f"      Drive状态: enabled={is_enabled}, current={is_current}, aria_disabled={aria_disabled}")
                    
                    if (is_current or 
                        (is_enabled and aria_disabled == 'false')):
                        print(f"    ✅ Drive步骤已激活或可用")
                        return True
                
                # 检查其他配置相关的导航项
                config_nav_items = ['Drive', 'Bodystyle', 'Colour', 'Interior', 'Extras']
                available_config_items = []
                for item_name in config_nav_items:
                    if item_name in nav_state:
                        item_info = nav_state[item_name]
                        if (item_info.get('enabled', False) and 
                            item_info.get('aria_disabled', 'true') == 'false'):
                            available_config_items.append(item_name)
                
                if available_config_items:
                    print(f"    ✅ 可用配置项: {', '.join(available_config_items)}")
                    return True
            
            # 检查方法2：URL变化
            current_url = self.driver.current_url
            config_url_keywords = ['drive', 'configure', 'build', 'config', 'bodystyle', 'colour', 'interior']
            url_indicates_config = any(keyword in current_url.lower() for keyword in config_url_keywords)
            
            if url_indicates_config:
                print(f"    ✅ URL显示已进入配置流程")
                return True
            
            # 检查方法3：页面内容变化
            try:
                config_content_selectors = [
                    '[data-testid*="drive"]',
                    '[data-testid*="config"]', 
                    '[class*="Drive"]',
                    '[class*="Configuration"]',
                    '[class*="ConfigStep"]',
                    'nav[data-testid="Navigation_Container"]',
                    'h1, h2, h3',  # 标题可能包含配置相关内容
                ]
                
                config_elements_found = 0
                for selector in config_content_selectors:
                    try:
                        elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                        for element in elements:
                            if element.is_displayed():
                                element_text = element.text.strip().lower()
                                config_keywords = ['drive', 'bodystyle', 'colour', 'interior', 'extras', 'configuration', 'build your']
                                
                                if any(keyword in element_text for keyword in config_keywords):
                                    config_elements_found += 1
                                    break
                    except Exception:
                        continue
                    
                    if config_elements_found > 0:
                        break
                
                if config_elements_found > 0:
                    print(f"    ✅ 检测到配置相关元素")
                    return True
                    
            except Exception:
                pass
            
            # 检查方法4：页面标题变化
            try:
                page_title = self.driver.title.lower()
                title_keywords = ['configure', 'build', 'customize', 'drive', 'bodystyle']
                if any(keyword in page_title for keyword in title_keywords):
                    print(f"    ✅ 页面标题显示配置流程")
                    return True
            except Exception:
                pass
            
            print(f"    ⚠️  未检测到配置流程入口")
            return False
            
        except Exception as e:
            print(f"    ❌ 验证配置入口时出错: {e}")
            return False
            
            # 检查方法2：URL变化
            current_url = self.driver.current_url
            if 'drive' in current_url.lower() or 'configure' in current_url.lower():
                print(f"    ✅ URL显示已进入配置流程")
                return True
            
            # 检查方法3：页面内容变化
            try:
                # 查找配置相关的元素
                config_elements = self.driver.find_elements(By.CSS_SELECTOR, 
                    '[data-testid*="drive"], [data-testid*="config"], [class*="Drive"], [class*="Configuration"]')
                if config_elements:
                    print(f"    ✅ 检测到配置相关元素")
                    return True
            except Exception:
                pass
            
            print(f"    ⚠️  未检测到配置流程入口")
            return False
            
        except Exception as e:
            print(f"    ❌ 验证配置入口时出错: {e}")
            return False
        """获取分页指示器信息"""
        try:
            # 查找分页指示器
            selectors = [
                'p.ProductTileSection__PaginationIndicator-sc-5noent-33.jLIuuv',
                'p[class*="PaginationIndicator"]',
                'p[aria-live="polite"][class*="Pagination"]',
                '[class*="PaginationIndicator"]'
            ]
            
            for selector in selectors:
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    for element in elements:
                        if element.is_displayed():
                            text = element.text.strip()
                            if text and ('of' in text.lower() or '-' in text):
                                return text
                except Exception:
                    continue
            
            return None
            
        except Exception as e:
            print(f"获取分页信息时出错: {e}")
            return None
    
    def get_pagination_info(self):
        """
        获取分页信息文本
        
        Returns:
            str or None: 分页信息文本（如 "3-7 of 7"）
        """
        try:
            # 尝试查找分页指示器
            pagination_selectors = [
                '.pagination-info',
                '[class*="pagination"]',
                '[class*="page-info"]',
                '[aria-label*="page" i]',
                'span[class*="current"]',
                'div[class*="current"]'
            ]
            
            for selector in pagination_selectors:
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    for element in elements:
                        if element.is_displayed():
                            text = element.text.strip()
                            # 检查是否包含分页格式（如 "1 of 3", "1-2 of 5"）
                            if 'of' in text.lower() and any(c.isdigit() for c in text):
                                return text
                except Exception:
                    continue
            
            # 如果找不到明确的分页指示器，返回默认值
            return "1 of 1"
            
        except Exception as e:
            print(f"获取分页信息时出错: {e}")
            return "1 of 1"
    
    def parse_pagination_info(self, pagination_text):
        """解析分页信息，返回(start, end, total)"""
        try:
            # 解析如 "3-7 of 7" 或 "1-2 of 7" 的格式
            if 'of' in pagination_text.lower():
                parts = pagination_text.lower().split('of')
                if len(parts) == 2:
                    range_part = parts[0].strip()
                    total_part = parts[1].strip()
                    
                    total = int(total_part)
                    
                    if '-' in range_part:
                        start, end = range_part.split('-')
                        return int(start), int(end), total
                    else:
                        # 单个数字
                        num = int(range_part)
                        return num, num, total
            
            return None, None, None
            
        except Exception as e:
            print(f"解析分页信息失败: {e}")
            return None, None, None
    
    def scrape_model_data(self):
        """抓取车型数据并使用实体类保存"""
        print("开始抓取车型数据...")
        
        # 创建车系实体类，并从配置中获取URL参数
        model_name = self.config.get('model', 'focus')
        url = self.config.get('sub_model', {}).get('url', '')
        
        # 从 URL 中解析目录信息
        catalog_id, series_code, default_paint = self.parse_url_parameters(url)
        
        car_series = CarSeries(
            car_series_name=model_name,
            catalog_id=catalog_id,
            series_code=series_code,
            default_paint=default_paint
        )
        
        print(f"车系信息: {model_name}, 目录ID: {catalog_id}, 车系代码: {series_code}, 默认颜色: {default_paint}")
        
        sub_models = []
        processed_models = set()  # 防止重复
        
        # 循环获取所有子车型 - 期望找到7个
        max_attempts = 20  # 增加最大尝试次数
        attempt = 0
        no_new_models_count = 0  # 连续没有新车型的次数
        target_models = 7  # 期望的车型数量
        seen_ranges = set()  # 记录已经处理过的分页范围
        
        print(f"开始抓取，期望找到 {target_models} 个车型...")
        
        while attempt < max_attempts and no_new_models_count < 5:
            print(f"第 {attempt + 1} 次尝试获取车型数据...")
            
            # 检查分页指示器
            pagination_info = self.get_pagination_info()
            current_range = None
            if pagination_info:
                print(f"分页信息: {pagination_info}")
                start, end, total = self.parse_pagination_info(pagination_info)
                if start and end and total:
                    current_range = f"{start}-{end}"
                    print(f"当前显示范围: {current_range} (共{total}个)")
                    
                    # 检查是否已经处理过这个范围
                    if current_range in seen_ranges:
                        print(f"范围 {current_range} 已处理过，跳过")
                        no_new_models_count += 1
                    else:
                        seen_ranges.add(current_range)
                        print(f"新范围 {current_range}，开始处理")
            
            # 获取当前可见的子车型（一次只处理一个，避免stale element问题）
            current_model = self.get_next_unprocessed_model(processed_models)
            
            new_models_found = False
            if current_model:
                model_name = current_model.get('model_name')
                if model_name and model_name not in processed_models:
                    sub_models.append(current_model)
                    processed_models.add(model_name)
                    new_models_found = True
                    print(f"✓ 发现新车型: {model_name} - {current_model.get('price', 'N/A')}")
                    
                    # 在获取Key Features后，等待页面稳定
                    print("等待页面稳定后继续...")
                    time.sleep(3)
            
            if new_models_found:
                no_new_models_count = 0
            else:
                no_new_models_count += 1
                print(f"本轮未发现新车型 ({no_new_models_count}/5)")
            
            # 检查是否已达到目标数量
            if len(sub_models) >= target_models:
                print(f"✓ 已获取到目标数量的车型 ({len(sub_models)}/{target_models})")
                break
            
            # 检查是否需要继续滚动获取更多车型
            should_continue = True
            if pagination_info and current_range:
                start, end, total = self.parse_pagination_info(pagination_info)
                if start and end and total:
                    # 如果已获取的车型数量少于显示范围的结束位置，继续尝试
                    if len(sub_models) < end:
                        print(f"当前已获取{len(sub_models)}个车型，但分页显示到第{end}个，继续尝试...")
                        should_continue = True
                    # 如果当前显示的已经是最后一组（end == total）且获取的车型数>=total，则停止
                    elif end >= total and len(sub_models) >= total:
                        print(f"已到达最后一页且获取完成 (获取{len(sub_models)}个，显示到第{end}个，共{total}个)")
                        should_continue = False
                    # 如果到达最后一页但还没获取完所有车型，最后尝试一次
                    elif end >= total:
                        print(f"最后一页，尝试获取剩余车型...")
                        should_continue = True
            
            if should_continue:
                # 如果我们在同一个分页范围内且没有新车型，尝试滚动
                if len(sub_models) >= target_models:
                    print(f"已达到目标数量 ({len(sub_models)}/{target_models})，停止抓取")
                    break
                    
                # 尝试滚动到下一个车型
                if not self.scroll_carousel():
                    print("无法继续滚动，尝试获取当前页面的剩余车型")
                    # 在停止前，尝试获取当前页面所有未处理的车型
                    for _ in range(3):  # 最多尝试3次
                        remaining_model = self.get_next_unprocessed_model(processed_models)
                        if remaining_model:
                            model_name = remaining_model.get('model_name')
                            if model_name and model_name not in processed_models:
                                sub_models.append(remaining_model)
                                processed_models.add(model_name)
                                print(f"✓ 最终发现车型: {model_name} - {remaining_model.get('price', 'N/A')}")
                        else:
                            break
                    break
            else:
                print("根据分页信息，已处理完所有页面")
                break
            
            attempt += 1
            time.sleep(2)  # 等待滚动和加载完成
        
        print(f"基本数据抓取完成，共获取到 {len(sub_models)} 个子车型")
        
        # 第二阶段：重置到第一页，逐个获取Key Features
        print("\n=== 开始第二阶段：获取Key Features ===")
        
        # 重置轮播到第一页
        if not self.reset_carousel_to_first_page():
            print("警告：无法重置到第一页，Key Features可能不准确")
        
        # 等待页面稳定
        time.sleep(3)
        
        # 为每个车型获取Key Features
        for i, model in enumerate(sub_models):
            model_name = model.get('model_name', 'Unknown')
            print(f"\n--- 处理第 {i+1}/{len(sub_models)} 个车型: {model_name} ---")
            
            # 获取当前第一个车型的元素（应该对应我们要处理的车型）
            try:
                # 查找第一个车型元素
                model_elements = self.driver.find_elements(By.CSS_SELECTOR, 'div[data-cy][class*="ProductTile"]')
                if not model_elements:
                    model_elements = self.driver.find_elements(By.CSS_SELECTOR, 'div[data-cy]')
                
                if model_elements:
                    first_element = model_elements[0]
                    current_model_name = first_element.get_attribute('data-cy')
                    print(f"当前第一个位置的车型: {current_model_name}")
                    
                    if current_model_name == model_name:
                        print(f"✓ 车型匹配，开始获取 {model_name} 的Key Features")
                        key_features = self.get_key_features_by_view_specifications(first_element, model_name)
                        model['Key Features'] = key_features
                        print(f"✓ {model_name} Key Features获取完成: {len(key_features)} 个")
                    else:
                        print(f"⚠️  车型不匹配，期望: {model_name}, 实际: {current_model_name}")
                        model['Key Features'] = ["", "", ""]
                else:
                    print("未找到车型元素")
                    model['Key Features'] = ["", "", ""]
                
                # 如果不是最后一个车型，滚动到下一页
                if i < len(sub_models) - 1:
                    print("滚动到下一个车型...")
                    if not self.scroll_carousel():
                        print("无法滚动到下一个车型")
                        # 为剩余车型设置空的Key Features
                        for j in range(i + 1, len(sub_models)):
                            sub_models[j]['Key Features'] = ["", "", ""]
                        break
                    time.sleep(2)  # 等待滚动完成
                    
            except Exception as e:
                print(f"处理 {model_name} 的Key Features时出错: {e}")
                model['Key Features'] = ["", "", ""]
        
        print(f"\n=== 全部数据抓取完成，共获取到 {len(sub_models)} 个子车型 ===")
        
        # 创建实体类对象
        for i, model in enumerate(sub_models):
            model_name_str = model.get('model_name', 'Unknown')
            price = model.get('price', '')
            key_features = model.get('Key Features', [])
            
            print(f"创建车款实体类: {model_name_str}")
            
            # 创建车款实体类
            car_object = CarObject(
                series_name=model_name,  # 车系名
                model_name=model_name_str,  # 车款名
                price=price,
                drive=""  # 暂时为空，后续可以扩展
            )
            
            # 添加Key Features
            for feature in key_features:
                if feature and feature.strip():  # 只添加非空的特性
                    car_object.add_key_feature(feature)
            
            # 添加一些默认的颜色（作为示例）
            car_object.add_color("red")
            car_object.add_color("blue")
            car_object.add_color("yellow")
            
            # 添加示例选装件
            extra1 = CarExtras("Blind Spot Information System with Blind Spot Assist & Trailer Coverage", "$1234")
            extra2 = CarExtras("Driver Assist Pack", "$575")
            extra3 = CarExtras("Openable Panorama Roof", "$1045")
            
            car_object.add_extra(extra1)
            car_object.add_extra(extra2)
            car_object.add_extra(extra3)
            
            # 添加车款到车系
            car_series.add_car_object(car_object)
        
        print(f"车系实体类中包含 {car_series.get_car_objects_count()} 个车款")
        
        return car_series
    
    def get_visible_sub_models(self):
        """获取当前可见的子车型数据"""
        models = []
        
        try:
            # 等待页面稳定
            time.sleep(1)
            
            # 尝试多种选择器来查找车型元素
            selectors = [
                'div[data-cy][class*="ProductTile"]',
                'div[data-cy]',
                '[class*="ProductTile"]',
                '[data-cy*="titanium"], [data-cy*="st-line"], [data-cy*="active"]'
            ]
            
            model_elements = []
            for selector in selectors:
                elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                if elements:
                    model_elements = elements
                    print(f"使用选择器 '{selector}' 找到 {len(elements)} 个车型元素")
                    break
            
            if not model_elements:
                print("警告：未找到任何车型元素")
                return models
            
            # 获取所有data-cy属性值以调试
            data_cy_values = []
            for element in model_elements:
                data_cy = element.get_attribute('data-cy')
                if data_cy:
                    data_cy_values.append(data_cy)
            
            print(f"发现的data-cy值: {data_cy_values}")
            
            for i, element in enumerate(model_elements):
                try:
                    # 获取data-cy属性作为调试信息
                    data_cy = element.get_attribute('data-cy')
                    print(f"处理元素 {i+1}: data-cy='{data_cy}'")
                    
                    # 检查元素是否可见 - 放宽可见性检查
                    is_displayed = element.is_displayed()
                    is_in_viewport = self.driver.execute_script(
                        "var rect = arguments[0].getBoundingClientRect();"
                        "return rect.width > 0 && rect.height > 0;", element
                    )
                    
                    if not is_displayed and not is_in_viewport:
                        print(f"元素 {i+1} ({data_cy}) 完全不可见，跳过")
                        continue
                    elif not is_displayed:
                        print(f"元素 {i+1} ({data_cy}) 不在视口但存在，尝试滚动到可见")
                        # 尝试滚动到元素可见区域
                        self.driver.execute_script(
                            "arguments[0].scrollIntoView({block: 'center', behavior: 'smooth'});", 
                            element
                        )
                        time.sleep(1)
                    
                    # 最终滚动到元素可见区域确保处理
                    self.driver.execute_script(
                        "arguments[0].scrollIntoView({block: 'center'});", 
                        element
                    )
                    time.sleep(0.5)
                    
                    # 提取车型名称和价格
                    model_data = self.extract_model_data(element)
                    
                    if model_data:
                        models.append(model_data)
                        print(f"成功提取: {model_data['model_name']} - {model_data['price']}")
                    else:
                        print(f"元素 {i+1} 数据提取失败")
                        
                except Exception as e:
                    print(f"解析第 {i+1} 个车型元素时出错: {e}")
                    continue
        
        except Exception as e:
            print(f"获取车型元素时出错: {e}")
        
        print(f"本轮共提取到 {len(models)} 个有效车型")
        return models
    
    def get_next_unprocessed_model(self, processed_models):
        """获取下一个未处理的车型（一次只处理一个，避免stale element问题）"""
        try:
            # 重新获取页面元素
            time.sleep(1)
            
            # 查找所有车型元素
            selectors = [
                'div[data-cy][class*="ProductTile"]',
                'div[data-cy]',
                '[class*="ProductTile"]'
            ]
            
            model_elements = []
            for selector in selectors:
                elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                if elements:
                    model_elements = elements
                    break
            
            if not model_elements:
                print("未找到任何车型元素")
                return None
            
            # 查找第一个未处理的车型
            for i, element in enumerate(model_elements):
                try:
                    data_cy = element.get_attribute('data-cy')
                    if data_cy and data_cy not in processed_models:
                        print(f"准备处理车型: {data_cy}")
                        
                        # 滚动到元素可见
                        self.driver.execute_script(
                            "arguments[0].scrollIntoView({block: 'center'});", 
                            element
                        )
                        time.sleep(1)
                        
                        # 提取车型数据
                        model_data = self.extract_model_data(element)
                        if model_data:
                            return model_data
                            
                except Exception as e:
                    print(f"处理车型元素 {i+1} 时出错: {e}")
                    continue
            
            print("没有找到未处理的车型")
            return None
            
        except Exception as e:
            print(f"获取下一个车型时出错: {e}")
            return None
    
    def extract_model_data(self, element):
        """从单个车型元素中提取数据"""
        try:
            # 提取车型名称
            name_elements = element.find_elements(
                By.CSS_SELECTOR, 'strong[class*="ProductTileAttributeValue"]'
            )
            
            model_name = None
            price = None
            
            for name_elem in name_elements:
                text = name_elem.text.strip()
                
                # 识别价格（以£开头）
                if text.startswith('£'):
                    price = text
                # 识别车型名称（不是价格的文本）
                elif text and not text.startswith('£') and not model_name:
                    model_name = text
            
            # 如果没有找到名称，尝试其他选择器
            if not model_name:
                data_cy = element.get_attribute('data-cy')
                if data_cy:
                    model_name = data_cy
            
            if model_name and price:
                # 点击View Specifications按钮获取Key Features
                key_features = self.get_key_features_by_view_specifications(element, model_name)
                
                return {
                    "model_name": model_name,
                    "price": price,
                    "color": [
                        {"color_name": "red", "price": "$1234"},
                        {"color_name": "yellow", "price": "$1234"},
                        {"color_name": "blue", "price": "$1234"}
                    ],  # 临时数据，后续需要实际抓取
                    "Key Features": key_features,  # 现在从实际点击View Specifications获取
                    "Extras": [
                        {"Extra_name": "Blind Spot Information System with Blind Spot Assist & Trailer Coverage", "price": "$1234"},
                        {"Extra_name": "Driver Assist Pack", "price": "$575"},
                        {"Extra_name": "BOpenable Panorama Roof", "price": "$1045"}
                    ]  # 临时数据，后续需要实际抓取
                }
            
        except Exception as e:
            print(f"提取车型数据时出错: {e}")
        
        return None
    
    def get_key_features_by_view_specifications(self, element, model_name):
        """通过点击View Specifications按钮获取Key Features"""
        key_features = []
        
        try:
            print(f"正在获取 {model_name} 的Key Features...")
            
            # 查找View Specifications按钮
            view_spec_selectors = [
                'button[data-cy="product-tile-overlay"]',
                'button[class*="ButtonAsLink"][data-cy="product-tile-overlay"]',
                '.ButtonAsLink-sc-6m73s-0.kMrUGm',
                'button[data-cy="product-tile-overlay"][class*="ButtonAsLink"]'
            ]
            
            view_spec_button = None
            for selector in view_spec_selectors:
                try:
                    buttons = element.find_elements(By.CSS_SELECTOR, selector)
                    for btn in buttons:
                        if btn.is_displayed() and 'view specifications' in btn.text.lower():
                            view_spec_button = btn
                            print(f"找到View Specifications按钮: {btn.text}")
                            break
                    if view_spec_button:
                        break
                except Exception:
                    continue
            
            # 如果没有找到具体的按钮，尝试更广泛的搜索
            if not view_spec_button:
                try:
                    all_buttons = element.find_elements(By.TAG_NAME, 'button')
                    for btn in all_buttons:
                        if btn.is_displayed() and 'view specifications' in btn.text.lower():
                            view_spec_button = btn
                            print(f"通过文本找到View Specifications按钮: {btn.text}")
                            break
                except Exception:
                    pass
            
            if not view_spec_button:
                print(f"警告：未找到 {model_name} 的View Specifications按钮")
                return ["", "", ""]  # 返回空的key features
            
            # 滚动到按钮可见并点击
            self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", view_spec_button)
            time.sleep(1)
            
            # 尝试点击View Specifications按钮
            try:
                view_spec_button.click()
                print(f"✓ 成功点击 {model_name} 的View Specifications按钮")
            except ElementClickInterceptedException:
                # 使用JavaScript点击
                self.driver.execute_script("arguments[0].click();", view_spec_button)
                print(f"✓ 使用JavaScript点击 {model_name} 的View Specifications按钮")
            
            # 对于Titanium车型，给予更多的等待时间
            if model_name.lower() == 'titanium':
                print("Titanium车型需要额外等待时间...")
                time.sleep(8)  # Titanium车型等待8秒
            else:
                time.sleep(3)  # 其他车型等待3秒
            
            # 查找Key Features
            key_features = self.extract_key_features_from_modal(model_name)
            
            # 关闭模态框或返回原页面
            self.close_modal_or_return()
            
            return key_features
            
        except Exception as e:
            print(f"获取 {model_name} Key Features时出错: {e}")
            # 确保关闭任何可能打开的模态框
            self.close_modal_or_return()
            return ["", "", ""]
    
    def extract_key_features_from_modal(self, model_name="未知"):
        """从模态框或新页面中提取Key Features"""
        key_features = []
        
        try:
            # 等待模态框完全显示
            print("等待模态框完全加载...")
            
            # 首先等待模态框容器出现
            try:
                modal_wait = WebDriverWait(self.driver, 15)
                modal_container = modal_wait.until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, 'div[data-cy="overlay-modal"]'))
                )
                print("✓ 模态框容器已加载")
                
                # 等待模态框内容完全渲染
                time.sleep(3)
                
                # 对于Titanium车型，额外等待并确保accordion展开
                if model_name.lower() == 'titanium':
                    print("Titanium车型额外等待...")
                    time.sleep(5)
                    
                    # 显式等待Key Features accordion按钮出现并确保展开
                    try:
                        accordion_wait = WebDriverWait(self.driver, 10)
                        accordion_button = accordion_wait.until(
                            EC.element_to_be_clickable((By.CSS_SELECTOR, 'button[data-cy="accordion-key-features-panel-overlay"]'))
                        )
                        
                        aria_expanded = accordion_button.get_attribute('aria-expanded')
                        print(f"Key Features accordion状态: {aria_expanded}")
                        
                        if aria_expanded == 'false':
                            print("展开Key Features accordion...")
                            accordion_button.click()
                            time.sleep(2)
                        
                    except Exception as e:
                        print(f"处理Titanium accordion时出错: {e}")
                        
            except Exception as e:
                print(f"等待模态框时出错: {e}")
                # 回退到简单等待
                time.sleep(8 if model_name.lower() == 'titanium' else 5)
            
            # 等待特定的Key Features容器加载，使用多次尝试
            print("等待Key Features容器加载...")
            
            # 现在直接尝试查找Key Features容器（应该已经加载完成）
            key_features_container = None
            
            # 使用WebDriverWait显式等待Key Features容器出现
            try:
                container_wait = WebDriverWait(self.driver, 15)
                key_features_container = container_wait.until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, 'dl[aria-label="Selected key features"][data-testid="Key_Features_ID"]'))
                )
                print("✓ 找到Key Features容器")
                
            except Exception as e:
                print(f"等待Key Features容器失败: {e}")
                # 备用选择器尝试
                try:
                    key_features_container = self.driver.find_element(By.CSS_SELECTOR, 'dl[data-testid="Key_Features_ID"]')
                    print("✓ 使用备用选择器找到Key Features容器")
                except Exception as e2:
                    print(f"备用选择器也失败: {e2}")
                    key_features_container = None
            
            if key_features_container:
                # 从找到的容器中提取所有功能项
                feature_item_selectors = [
                    'dt',  # definition term
                    'dd',  # definition description  
                    'li',  # list items
                    'div[class*="feature"]',
                    'span[class*="feature"]',
                    'p'
                ]
                
                for item_selector in feature_item_selectors:
                    try:
                        feature_items = key_features_container.find_elements(By.CSS_SELECTOR, item_selector)
                        if feature_items:
                            print(f"在容器中使用选择器 '{item_selector}' 找到 {len(feature_items)} 个功能项")
                            
                            temp_features = []
                            for item in feature_items:
                                if item.is_displayed():
                                    feature_text = item.text.strip()
                                    # 过滤有效的功能描述
                                    if (feature_text and 
                                        len(feature_text) > 5 and 
                                        len(feature_text) < 200 and
                                        not feature_text.lower().startswith('key features') and
                                        feature_text not in temp_features):
                                        temp_features.append(feature_text)
                            
                            if temp_features:
                                key_features = temp_features
                                print(f"✓ 从容器中提取到 {len(key_features)} 个Key Features")
                                break
                                
                    except Exception as item_error:
                        print(f"提取功能项时出错: {item_error}")
                        continue
            
            # 如果还没找到，尝试更广泛的搜索
            if not key_features:
                print("尝试广泛搜索Key Features...")
                broad_selectors = [
                    # 在整个页面中查找包含features的区域
                    '*[data-testid*="Key_Features"] *',
                    '*[aria-label*="key features"] *',
                    '*[class*="feature"] li',
                    '*[class*="Feature"] li',
                    'dl dt',
                    'dl dd',
                    # 查找列表结构
                    'ul li',
                    'ol li'
                ]
                
                for selector in broad_selectors:
                    try:
                        elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                        if elements:
                            temp_features = []
                            for elem in elements[:20]:  # 最多检查20个元素
                                if elem.is_displayed():
                                    text = elem.text.strip()
                                    # 更严格的过滤条件
                                    if (text and 
                                        len(text) > 10 and 
                                        len(text) < 150 and
                                        not text.lower().startswith(('key', 'feature', 'specification')) and
                                        '"' in text or 'alloy' in text.lower() or 'touchscreen' in text.lower() or 'system' in text.lower()):
                                        temp_features.append(text)
                            
                            if len(temp_features) >= 3:
                                key_features = temp_features
                                print(f"✓ 通过广泛搜索提取到 {len(key_features)} 个Key Features")
                                break
                    except Exception:
                        continue
            
            # 如果仍然没有找到足够的features，返回找到的或空列表
            if not key_features:
                print("警告：未找到Key Features，返回空列表")
                return ["", "", ""]
            
            # 清理和去重
            cleaned_features = []
            for feature in key_features:
                if feature and feature not in cleaned_features:
                    cleaned_features.append(feature)
            
            print(f"✓ 最终提取到 {len(cleaned_features)} 个Key Features:")
            for i, feature in enumerate(cleaned_features[:10], 1):  # 显示前10个
                print(f"  {i}. {feature}")
            
            return cleaned_features  # 返回所有找到的features，不限制数量
            
        except Exception as e:
            print(f"提取Key Features时出错: {e}")
            return ["", "", ""]
    
    def close_modal_or_return(self):
        """关闭模态框或返回原页面"""
        try:
            # 首先尝试按ESC键（最安全的方法）
            try:
                from selenium.webdriver.common.keys import Keys
                body = self.driver.find_element(By.TAG_NAME, 'body')
                body.send_keys(Keys.ESCAPE)
                print("✓ 使用ESC键关闭模态框")
                time.sleep(2)
                
                # 检查是否成功返回原页面（检查是否有车型元素）
                model_elements = self.driver.find_elements(By.CSS_SELECTOR, 'div[data-cy][class*="ProductTile"]')
                if model_elements:
                    print("✓ 成功返回车型列表页面")
                    return
            except Exception as e:
                print(f"ESC键方法失败: {e}")
            
            # 尝试查找并点击关闭按钮
            close_selectors = [
                '[aria-label*="close"]',
                '[class*="close"]',
                '[data-testid*="close"]',
                '.modal-close',
                '.close-btn',
                'button[class*="close"]',
                # 返回按钮
                '[aria-label*="back"]',
                'button[class*="back"]',
                'button[class*="return"]'
            ]
            
            for selector in close_selectors:
                try:
                    close_buttons = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    for btn in close_buttons:
                        if btn.is_displayed():
                            btn.click()
                            print(f"✓ 成功点击关闭按钮: {selector}")
                            time.sleep(2)
                            
                            # 检查是否成功返回
                            model_elements = self.driver.find_elements(By.CSS_SELECTOR, 'div[data-cy][class*="ProductTile"]')
                            if model_elements:
                                return
                except Exception:
                    continue
            
            # 如果上述方法都失败，最后尝试导航回原页面（作为最后手段）
            print("尝试导航回原页面...")
            original_url = self.config['sub_model']['url']
            self.driver.get(original_url)
            print("✓ 重新加载原页面")
            time.sleep(3)
                
        except Exception as e:
            print(f"关闭模态框时出错: {e}")
            # 最后的fallback - 重新加载页面
            try:
                original_url = self.config['sub_model']['url']
                self.driver.get(original_url)
                print("✓ 重新加载原页面作为fallback")
                time.sleep(3)
            except Exception:
                print("警告：无法返回原页面")
    
    def scroll_carousel(self):
        """滚动轮播组件"""
        try:
            # 方法1：使用正确的下一页按钮选择器
            next_button_selectors = [
                'button[aria-label="Move to next element"][action="next"]',
                'button.PaginationArrowBtn-sc-1o074yf-0.fXZRaw[action="next"]',
                'button[action="next"]',
                'button[aria-label*="Move to next"]',
                '.PaginationArrowBtn-sc-1o074yf-0[action="next"]'
            ]
            
            for selector in next_button_selectors:
                try:
                    next_buttons = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    
                    for button in next_buttons:
                        if button.is_displayed():
                            # 检查按钮是否可用（不是disabled状态）
                            aria_disabled = button.get_attribute('aria-disabled')
                            if aria_disabled == 'true':
                                print("下一页按钮已禁用，可能已到达最后一页")
                                return False
                            
                            print(f"找到下一页按钮，使用选择器: {selector}")
                            
                            # 滚动到按钮可见
                            self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", button)
                            time.sleep(0.5)
                            
                            # 点击按钮
                            try:
                                button.click()
                                print("✓ 成功点击下一页按钮")
                                time.sleep(2)  # 等待轮播动画完成
                                return True
                            except ElementClickInterceptedException:
                                # 使用JavaScript点击
                                self.driver.execute_script("arguments[0].click();", button)
                                print("✓ 使用JavaScript点击下一页按钮")
                                time.sleep(2)
                                return True
                                
                except Exception as selector_error:
                    print(f"选择器 {selector} 失败: {selector_error}")
                    continue
            
            # 方法2：查找通用的下一页按钮
            generic_selectors = [
                '[aria-label*="next"], [class*="next"], [class*="arrow"], button[class*="right"]'
            ]
            
            for selector in generic_selectors:
                try:
                    buttons = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    for button in buttons:
                        if button.is_displayed() and button.is_enabled():
                            button_text = button.get_attribute('aria-label') or button.text
                            if 'next' in button_text.lower():
                                print(f"找到通用下一页按钮: {button_text}")
                                self.driver.execute_script("arguments[0].click();", button)
                                time.sleep(2)
                                return True
                except Exception:
                    continue
            
            # 方法3：使用JavaScript直接滚动轮播容器
            print("尝试JavaScript滚动方法")
            scroll_scripts = [
                # 查找轮播容器并滚动
                """
                var carousels = document.querySelectorAll('[class*="carousel"], [class*="slider"], [class*="ProductTile"]');
                for(var i = 0; i < carousels.length; i++) {
                    if(carousels[i].scrollWidth > carousels[i].clientWidth) {
                        carousels[i].scrollLeft += 400;
                        return true;
                    }
                }
                return false;
                """,
                # 更通用的横向滚动
                """
                var containers = document.querySelectorAll('div[class*="Wrapper"], div[class*="Container"]');
                for(var i = 0; i < containers.length; i++) {
                    if(containers[i].scrollWidth > containers[i].clientWidth) {
                        containers[i].scrollLeft += 400;
                        return true;
                    }
                }
                return false;
                """
            ]
            
            for script in scroll_scripts:
                try:
                    result = self.driver.execute_script(script)
                    if result:
                        print("✓ JavaScript滚动成功")
                        time.sleep(2)
                        return True
                except Exception as script_error:
                    print(f"JavaScript滚动失败: {script_error}")
                    continue
            
            print("所有滚动方法都失败了")
            return False
            
        except Exception as e:
            print(f"滚动操作失败: {e}")
            return False
    
    def reset_carousel_to_first_page(self):
        """重置轮播到第一页"""
        try:
            print("正在重置轮播到第一页...")
            max_attempts = 10  # 最多尝试10次回到第一页
            
            for attempt in range(max_attempts):
                # 检查当前分页信息
                start, end, total = self.parse_pagination_info(self.get_pagination_info())
                print(f"当前分页: {start}-{end} of {total}")
                
                if start == 1:
                    print("✓ 已经在第一页")
                    return True
                
                # 查找上一页按钮
                prev_button_selectors = [
                    'button[aria-label="Move to previous element"][action="previous"]',
                    'button[action="previous"]',
                    'button[aria-label*="previous"]',
                    '.PaginationArrowBtn-sc-1o074yf-0.fXZRaw[action="previous"]'
                ]
                
                prev_button = None
                for selector in prev_button_selectors:
                    buttons = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    for btn in buttons:
                        if btn.is_displayed():
                            prev_button = btn
                            break
                    if prev_button:
                        break
                
                if not prev_button:
                    print("未找到上一页按钮")
                    return False
                
                # 检查按钮是否可用
                aria_disabled = prev_button.get_attribute('aria-disabled')
                if aria_disabled == 'true':
                    print("上一页按钮已禁用，可能已在第一页")
                    return True
                
                # 点击上一页按钮
                try:
                    prev_button.click()
                    print(f"✓ 点击上一页按钮 (尝试 {attempt + 1}/{max_attempts})")
                except ElementClickInterceptedException:
                    self.driver.execute_script("arguments[0].click();", prev_button)
                    print(f"✓ 使用JavaScript点击上一页按钮 (尝试 {attempt + 1}/{max_attempts})")
                
                # 等待页面更新
                time.sleep(2)
            
            print("警告：无法重置到第一页")
            return False
            
        except Exception as e:
            print(f"重置轮播到第一页时出错: {e}")
            return False
    
    def save_data(self, car_series):
        """使用实体类保存数据到JSON文件"""
        try:
            output_file = self.config['sub_model']['output_file']
            
            print(f"正在保存数据到: {output_file}")
            
            # 使用实体类的to_dict方法转换为字典
            data = car_series.to_dict()
            
            # 保存为新格式
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(data, f, indent=4, ensure_ascii=False)
            
            print(f"✓ 数据保存成功（新格式）")
            print(f"✓ 车系: {car_series.car_series_name}")
            print(f"✓ 共有 {car_series.get_car_objects_count()} 个车款")
            
            # 显示抓取结果摘要
            for i, car_object in enumerate(car_series.car_object_list, 1):
                print(f"  {i}. {car_object.model_name} - {car_object.price} - {car_object.getKeyFeaturesCount()}个关键特性")
                
        except Exception as e:
            print(f"保存数据时出错: {e}")
            raise
    
    def cleanup(self):
        """清理资源"""
        if self.driver:
            print("正在关闭浏览器...")
            try:
                self.driver.quit()
                print("浏览器已关闭")
            except Exception as e:
                print(f"关闭浏览器时出错: {e}")
    
    def extract_colour_options_with_scrolling(self):
        """
        实现颜色选项的滚动抓取机制
        模拟上下滚动显示全部颜色选项
        
        Returns:
            list: 颜色选项列表
        """
        print("    🎨 开始滚动抓取颜色选项...")
        
        colour_options = []
        
        try:
            # 步骤1：检测颜色选项容器
            colour_container = self.detect_colour_container()
            if not colour_container:
                print("    ⚠️  未找到颜色选项容器")
                return []
            
            print("    ✓ 找到颜色选项容器")
            
            # 步骤2：初始抓取可见颜色选项
            initial_colours = self.extract_visible_colour_options(colour_container)
            colour_options.extend(initial_colours)
            print(f"    ✓ 初始抓取到 {len(initial_colours)} 个颜色选项")
            
            # 步骤3：实现滚动机制显示更多颜色
            additional_colours = self.scroll_and_extract_more_colours(colour_container, initial_colours)
            
            # 去重并合并结果
            all_colours = self.deduplicate_colour_options(colour_options + additional_colours)
            
            print(f"    🎆 总共抓取到 {len(all_colours)} 个独特颜色选项")
            return all_colours
            
        except Exception as e:
            print(f"    ❌ 滚动抓取颜色选项时出错: {e}")
            return colour_options
    
    def detect_colour_container(self):
        """
        检测颜色选项容器
        根据用户澄清：只有在 simplebar-content 容器里的条目才是颜色
        
        Returns:
            WebElement or None: 颜色容器元素
        """
        print("      🔍 检测颜色选项容器...")
        
        try:
            # 根据用户澄清的业务逻辑：只查找 simplebar-content 容器
            container = self.driver.find_element(By.CSS_SELECTOR, 'div.simplebar-content[style*="padding: 0px"]')
            if container.is_displayed():
                print("        ✓ 找到simplebar-content颜色容器")
                return container
        except Exception:
            pass
        
        # 备用选择器
        try:
            container = self.driver.find_element(By.CSS_SELECTOR, 'div.simplebar-content')
            if container.is_displayed():
                print("        ✓ 找到simplebar-content容器（备用）")
                return container
        except Exception:
            pass
        
        print("        ❌ 未找到simplebar-content颜色容器")
        return None
    
    def extract_visible_colour_options(self, container):
        """
        提取当前可见的颜色选项
        根据用户澄清：只识别 ColoursSection__ColourItemWrapper 标签内的颜色选项
        
        Args:
            container (WebElement): 颜色容器元素
            
        Returns:
            list: 可见颜色选项列表
        """
        colour_options = []
        
        try:
            # 根据用户澄清的业务逻辑：查找 ColoursSection__ColourItemWrapper 元素
            colour_selector = 'div[role="radio"][class*="ColoursSection__ColourItemWrapper"]'
            
            elements = container.find_elements(By.CSS_SELECTOR, colour_selector)
            print(f"        找到 {len(elements)} 个颜色选项元素")
            
            for element in elements:
                if element.is_displayed():
                    colour_data = self.extract_colour_option_data(element)
                    if colour_data:
                        colour_options.append(colour_data)
                        print(f"          ✓ 提取颜色: {colour_data['name']} - {colour_data['price']}")
        
        except Exception as e:
            print(f"        提取颜色选项时出错: {e}")
        
        return colour_options
    
    def scroll_and_extract_more_colours(self, container, initial_colours):
        """
        通过滚动显示更多颜色选项
        
        Args:
            container (WebElement): 颜色容器
            initial_colours (list): 初始可见的颜色选项
            
        Returns:
            list: 通过滚动获取的颜色选项
        """
        print("      📜 开始滚动显示更多颜色...")
        
        additional_colours = []
        
        try:
            # 获取初始颜色名称集合
            initial_names = set(colour.get('name', '') for colour in initial_colours)
            
            # 定义滚动参数
            scroll_attempts = 5
            scroll_distance = 300
            
            for i in range(scroll_attempts):
                print(f"        🔽 第 {i+1} 次滚动...")
                
                # 向下滚动
                self.driver.execute_script(f"""
                    arguments[0].scrollBy(0, {scroll_distance});
                """, container)
                
                time.sleep(1)  # 等待滚动动画完成
                
                # 抓取新显示的颜色选项
                new_colours = self.extract_visible_colour_options(container)
                
                # 检查是否有新颜色
                found_new = False
                for colour in new_colours:
                    colour_name = colour.get('name', '')
                    if colour_name and colour_name not in initial_names:
                        additional_colours.append(colour)
                        initial_names.add(colour_name)
                        found_new = True
                        print(f"          ✓ 发现新颜色: {colour_name}")
                
                if not found_new:
                    print(f"        ℹ️  第 {i+1} 次滚动未发现新颜色")
                
                # 向上滚动一些，模拟真实用户行为
                if i < scroll_attempts - 1:
                    self.driver.execute_script(f"""
                        arguments[0].scrollBy(0, -{scroll_distance // 2});
                    """, container)
                    time.sleep(0.5)
            
            print(f"      🎆 滚动完成，发现 {len(additional_colours)} 个新颜色选项")
            return additional_colours
            
        except Exception as e:
            print(f"      ❌ 滚动抓取时出错: {e}")
            return additional_colours
    
    def extract_colour_option_data(self, element):
        """
        从颜色选项元素中提取数据
        根据用户澄清：从 aria-label="Race Red £0" 解析颜色名称和价格
        
        Args:
            element (WebElement): 颜色选项元素
            
        Returns:
            dict or None: 颜色选项数据
        """
        try:
            name = ''
            price = ''
            colour_code = ''
            
            # 根据用户澄清的业务逻辑：从 aria-label 属性解析数据
            aria_label = element.get_attribute('aria-label')
            if aria_label:
                # 解析 aria-label="Race Red £0"
                if '£' in aria_label:
                    # 找到£符号的位置
                    pound_index = aria_label.find('£')
                    name = aria_label[:pound_index].strip()  # £前面的是颜色名称
                    price = aria_label[pound_index:].strip()  # £及之后是价格字符串
                else:
                    # 如果没有£符号，整个作为颜色名称
                    name = aria_label.strip()
                    price = 'Standard'
            
            # 提取颜色代码
            colour_code = element.get_attribute('data-item-code') or ''
            
            # 验证数据
            if name and len(name) > 0:
                return {
                    'name': name,
                    'price': price if price else 'Standard',
                    'description': '',
                    'colour_code': colour_code,
                    'element_text': aria_label
                }
            
            return None
            
        except Exception as e:
            print(f"          提取颜色选项数据时出错: {e}")
            return None
    
    def deduplicate_colour_options(self, colour_options):
        """
        去除重复的颜色选项
        
        Args:
            colour_options (list): 颜色选项列表
            
        Returns:
            list: 去重后的颜色选项列表
        """
        seen_names = set()
        unique_colours = []
        
        for colour in colour_options:
            colour_name = colour.get('name', '')
            if colour_name and colour_name not in seen_names:
                seen_names.add(colour_name)
                unique_colours.append(colour)
        
        return unique_colours
    
    def update_car_objects_with_colour_data(self, car_series, target_model, colour_data):
        """
        将Colour数据更新到每个CarObject中
        
        Args:
            car_series (CarSeries): 车系对象
            target_model (str): 目标车型名称
            colour_data (list): 颜色数据列表
        """
        print(f"    🔄 为 {target_model} 的每个CarObject添加Colour数据...")
        
        try:
            updated_objects = 0
            colour_names = [colour.get('name', '') for colour in colour_data if colour.get('name')]
            
            # 遍历所有CarObject，找到匹配的车型
            for car_object in car_series.car_object_list:
                if car_object.model_name.lower() == target_model.lower():
                    # 清空现有的colors
                    car_object.colors = colour_names.copy()
                    updated_objects += 1
                    
                    print(f"      ✓ 为 {target_model} + {car_object.drive} 添加 {len(colour_names)} 个颜色选项")
            
            print(f"    ✅ 共更新了 {updated_objects} 个CarObject，添加了 {len(colour_names)} 个颜色选项")
            
        except Exception as e:
            print(f"    ❌ 更新Colour数据时出错: {e}")
    
    def scrape_interior_data(self):
        """
        抓取Interior页面的数据
        
        Returns:
            list: 内饰选项列表
        """
        print("    🪑 开始抓取Interior选项...")
        
        try:
            # 步骤1：导航到Interior页面
            if not self.navigate_to_interior_page():
                print("    ❌ 无法进入Interior页面")
                return []
            
            # 步骤2：等待Interior页面加载
            print("    ⏳ 等待Interior页面加载...")
            time.sleep(3)
            
            # 步骤3：抓取内饰选项
            interior_options = self.extract_interior_options()
            
            if interior_options:
                print(f"    ✅ 成功抓取到 {len(interior_options)} 个内饰选项")
                for i, interior in enumerate(interior_options, 1):
                    print(f"      {i}. {interior.get('name', 'Unknown')} - {interior.get('price', 'N/A')}")
            else:
                print("    ⚠️  未找到内饰选项")
                # 使用默认内饰数据
                interior_options = [
                    {'name': 'Charcoal Black', 'price': 'Standard', 'description': 'Standard interior'},
                    {'name': 'Ebony Sensico', 'price': '+£400', 'description': 'Premium interior'}
                ]
            
            return interior_options
            
        except Exception as e:
            print(f"    ❌ Interior数据抓取出错: {e}")
            return []
    
    def navigate_to_interior_page(self):
        """
        导航到Interior配置页面
        
        Returns:
            bool: 是否成功进入Interior页面
        """
        print("    🧸 导航到Interior页面...")
        
        try:
            # 等待页面更新后再导航
            time.sleep(2)
            
            # 方法1：查找导航栏中的Interior按钮
            nav_state = self.get_navigation_state()
            if nav_state and 'Interior' in nav_state:
                interior_nav_info = nav_state['Interior']
                
                if (interior_nav_info.get('enabled', False) and 
                    interior_nav_info.get('aria_disabled', 'true') == 'false'):
                    
                    interior_button = self.find_navigation_button('Interior')
                    if interior_button:
                        print("      ✓ 找到Interior导航按钮")
                        self.click_element_safely(interior_button)
                        time.sleep(2)
                        
                        if self.verify_interior_page_loaded():
                            print("      ✅ 成功进入Interior页面")
                            return True
            
            # 方法2：查找Interior相关的直接链接
            interior_selectors = [
                'a[href*="interior"]',
                'button[data-testid*="interior"]',
                '[class*="Interior"] button',
                'button[aria-label*="interior" i]'
            ]
            
            for selector in interior_selectors:
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    for element in elements:
                        if element.is_displayed() and element.is_enabled():
                            print(f"      ✓ 找到Interior链接: {selector}")
                            self.click_element_safely(element)
                            time.sleep(2)
                            
                            if self.verify_interior_page_loaded():
                                print("      ✅ 通过直接链接进入Interior页面")
                                return True
                except Exception:
                    continue
            
            # 方法3：检查当前URL是否已经在Interior页面
            current_url = self.driver.current_url.lower()
            if 'interior' in current_url:
                print("      ✓ 当前URL显示已在Interior页面")
                return self.verify_interior_page_loaded()
            
            print("      ❌ 所有Interior导航方法都失败")
            return False
            
        except Exception as e:
            print(f"      ❌ 导航到Interior页面时出错: {e}")
            return False
    
    def verify_interior_page_loaded(self):
        """
        验证Interior页面是否已加载
        
        Returns:
            bool: 是否已加载Interior页面
        """
        try:
            # 检查方法1：查找Interior相关的页面元素
            interior_indicators = [
                '[data-testid*="interior"]',
                '[class*="Interior"]',
                'h1, h2, h3[class*="interior" i]',
                'div[class*="InteriorConfiguration"]'
            ]
            
            for selector in interior_indicators:
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    if elements:
                        visible_elements = [el for el in elements if el.is_displayed()]
                        if visible_elements:
                            print(f"      ✓ 检测到Interior页面元素: {selector}")
                            return True
                except Exception:
                    continue
            
            # 检查方法2：URL验证
            current_url = self.driver.current_url.lower()
            if 'interior' in current_url:
                print(f"      ✓ URL显示在Interior页面")
                return True
            
            # 检查方法3：导航状态
            nav_state = self.get_navigation_state()
            if nav_state and 'Interior' in nav_state:
                interior_info = nav_state['Interior']
                if interior_info.get('current', False):
                    print(f"      ✓ 导航状态显示在Interior页面")
                    return True
            
            return False
            
        except Exception as e:
            print(f"      验证Interior页面时出错: {e}")
            return False
    
    def extract_interior_options(self):
        """
        提取Interior页面的内饰选项
        根据用户澄清：只有ButtonAsLink按钮内容才是Interior
        
        Returns:
            list: 内饰选项列表
        """
        print("    🔍 提取Interior选项...")
        
        interior_options = []
        
        try:
            # 等待页面稳定
            time.sleep(2)
            
            # 根据用户澄清的业务逻辑：只查找ButtonAsLink按钮
            button_selector = 'button.ButtonAsLink-sc-6m73s-0'
            
            button_elements = self.driver.find_elements(By.CSS_SELECTOR, button_selector)
            print(f"      🔍 找到 {len(button_elements)} 个ButtonAsLink按钮")
            
            found_options = []
            
            for button_element in button_elements:
                if button_element.is_displayed():
                    option_data = self.extract_interior_option_data(button_element)
                    if option_data and option_data not in found_options:
                        found_options.append(option_data)
                        print(f"      ✓ 找到Interior选项: {option_data['name']} - {option_data['price']}")
            
            interior_options = found_options
            
            # 如果没找到，创建默认选项
            if not interior_options:
                print(f"      ⚠️  未找到Interior选项，使用默认值")
                interior_options = [
                    {'name': 'Charcoal Black', 'price': 'Standard', 'description': 'Standard interior'},
                    {'name': 'Ebony Sensico', 'price': '+£400', 'description': 'Premium interior'}
                ]
            
            return interior_options
            
        except Exception as e:
            print(f"      ❌ 提取Interior选项时出错: {e}")
            return []
    
    def extract_interior_option_data(self, element):
        """
        从ButtonAsLink内饰选项元素中提取数据
        根据用户澄清：按钮内容作为Interior名称，同一P标签里的span作为价格
        
        Args:
            element (WebElement): ButtonAsLink内饰选项元素
            
        Returns:
            dict or None: 内饰选项数据
        """
        try:
            name = ''
            price = ''
            description = ''
            
            # 根据用户澄清的业务逻辑：按钮内容是Interior名称
            if element.tag_name.lower() == 'button' and 'ButtonAsLink' in element.get_attribute('class'):
                name = element.text.strip()
                
                # 查找同一P标签里的span价格信息
                try:
                    # 向上查找包含该按钮的P标签
                    p_element = element.find_element(By.XPATH, './ancestor::p[1]')
                    
                    # 在P标签内查找span价格元素
                    price_spans = p_element.find_elements(By.CSS_SELECTOR, 'span.Attributes__AttributeBaseStyle-sc-1cpcw4h-0.Attributes__AttributeValue-sc-1cpcw4h-3')
                    
                    for span in price_spans:
                        if span.is_displayed():
                            span_text = span.text.strip()
                            if span_text and ('£' in span_text or 'Standard' in span_text.lower()):
                                price = span_text
                                break
                    
                    # 如果没找到特定的span，在P标签中搜索任何包含£的span
                    if not price:
                        all_spans = p_element.find_elements(By.CSS_SELECTOR, 'span')
                        for span in all_spans:
                            if span.is_displayed():
                                span_text = span.text.strip()
                                if span_text and '£' in span_text:
                                    price = span_text
                                    break
                                    
                except Exception as e:
                    print(f"          ⚠️  查找P标签价格旰出错: {e}")
                    # 如果找不到P标签，尝试在按钮附近查找价格
                    try:
                        parent = element.find_element(By.XPATH, './parent::*')
                        price_elements = parent.find_elements(By.CSS_SELECTOR, 'span')
                        for price_elem in price_elements:
                            if price_elem.is_displayed():
                                price_text = price_elem.text.strip()
                                if price_text and '£' in price_text:
                                    price = price_text
                                    break
                    except Exception:
                        pass
            
            # 设置默认价格
            if not price:
                price = 'Standard'
            
            # 验证数据
            if name and len(name) > 1:
                return {
                    'name': name,
                    'price': price,
                    'description': description,
                    'element_text': name
                }
            
            return None
            
        except Exception as e:
            print(f"        提取Interior选项数据时出错: {e}")
            return None
    
    def update_car_objects_with_interior_data(self, car_series, target_model, interior_data):
        """
        将Interior数据更新到每个CarObject中
        
        Args:
            car_series (CarSeries): 车系对象
            target_model (str): 目标车型名称
            interior_data (list): 内饰数据列表
        """
        print(f"    🔄 为 {target_model} 的每个CarObject添加Interior数据...")
        
        try:
            updated_objects = 0
            interior_names = [interior.get('name', '') for interior in interior_data if interior.get('name')]
            
            # 遍历所有CarObject，找到匹配的车型
            for car_object in car_series.car_object_list:
                if car_object.model_name.lower() == target_model.lower():
                    # 清空现有的interiors
                    car_object.interiors = interior_names.copy()
                    updated_objects += 1
                    
                    print(f"      ✓ 为 {target_model} + {car_object.drive} 添加 {len(interior_names)} 个内饰选项")
            
            print(f"    ✅ 共更新了 {updated_objects} 个CarObject，添加了 {len(interior_names)} 个内饰选项")
            
        except Exception as e:
            print(f"    ❌ 更新Interior数据时出错: {e}")
    
    def scrape_extras_data(self):
        """
        抓取Extras页面的数据
        
        Returns:
            list: 选装件选项列表
        """
        print("    ⚙️  开始抓取Extras选项...")
        
        try:
            # 步骤1：导航到Extras页面
            if not self.navigate_to_extras_page():
                print("    ❌ 无法进入Extras页面")
                return []
            
            # 步骤2：等待Extras页面加载
            print("    ⏳ 等待Extras页面加载...")
            time.sleep(3)
            
            # 步骤3：抓取选装件选项
            extras_options = self.extract_extras_options()
            
            if extras_options:
                print(f"    ✅ 成功抓取到 {len(extras_options)} 个选装件选项")
                for i, extra in enumerate(extras_options, 1):
                    print(f"      {i}. {extra.get('name', 'Unknown')} - {extra.get('price', 'N/A')}")
            else:
                print("    ⚠️  未找到选装件选项")
                # 使用默认选装件数据
                extras_options = [
                    {'name': 'Blind Spot Information System', 'price': '+£450', 'description': 'Safety feature'},
                    {'name': 'Premium Audio System', 'price': '+£750', 'description': 'Entertainment system'}
                ]
            
            return extras_options
            
        except Exception as e:
            print(f"    ❌ Extras数据抓取出错: {e}")
            return []
    
    def navigate_to_extras_page(self):
        """
        导航到Extras配置页面
        
        Returns:
            bool: 是否成功进入Extras页面
        """
        print("    🧭 导航到Extras页面...")
        
        try:
            # 等待页面更新后再导航
            time.sleep(2)
            
            # 方法1：查找导航栏中的Extras按钮
            nav_state = self.get_navigation_state()
            if nav_state and 'Extras' in nav_state:
                extras_nav_info = nav_state['Extras']
                
                if (extras_nav_info.get('enabled', False) and 
                    extras_nav_info.get('aria_disabled', 'true') == 'false'):
                    
                    extras_button = self.find_navigation_button('Extras')
                    if extras_button:
                        print("      ✓ 找到Extras导航按钮")
                        self.click_element_safely(extras_button)
                        time.sleep(2)
                        
                        if self.verify_extras_page_loaded():
                            print("      ✅ 成功进入Extras页面")
                            return True
            
            # 方法2：查找Extras相关的直接链接
            extras_selectors = [
                'a[href*="extras"]',
                'a[href*="extra"]',
                'button[data-testid*="extras"]',
                'button[data-testid*="extra"]',
                '[class*="Extras"] button',
                '[class*="Extra"] button',
                'button[aria-label*="extras" i]',
                'button[aria-label*="extra" i]'
            ]
            
            for selector in extras_selectors:
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    for element in elements:
                        if element.is_displayed() and element.is_enabled():
                            print(f"      ✓ 找到Extras链接: {selector}")
                            self.click_element_safely(element)
                            time.sleep(2)
                            
                            if self.verify_extras_page_loaded():
                                print("      ✅ 通过直接链接进入Extras页面")
                                return True
                except Exception:
                    continue
            
            # 方法3：检查当前URL是否已经在Extras页面
            current_url = self.driver.current_url.lower()
            if 'extras' in current_url or 'extra' in current_url:
                print("      ✓ 当前URL显示已在Extras页面")
                return self.verify_extras_page_loaded()
            
            print("      ❌ 所有Extras导航方法都失败")
            return False
            
        except Exception as e:
            print(f"      ❌ 导航到Extras页面时出错: {e}")
            return False
    
    def verify_extras_page_loaded(self):
        """
        验证Extras页面是否已加载
        
        Returns:
            bool: 是否已加载Extras页面
        """
        try:
            # 检查方法1：查找Extras相关的页面元素
            extras_indicators = [
                '[data-testid*="extras"]',
                '[data-testid*="extra"]',
                '[class*="Extras"]',
                '[class*="Extra"]',
                'h1, h2, h3[class*="extras" i]',
                'h1, h2, h3[class*="extra" i]',
                'div[class*="ExtrasConfiguration"]',
                'div[class*="ExtraConfiguration"]'
            ]
            
            for selector in extras_indicators:
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    if elements:
                        visible_elements = [el for el in elements if el.is_displayed()]
                        if visible_elements:
                            print(f"      ✓ 检测到Extras页面元素: {selector}")
                            return True
                except Exception:
                    continue
            
            # 检查方法2：URL验证
            current_url = self.driver.current_url.lower()
            if 'extras' in current_url or 'extra' in current_url:
                print(f"      ✓ URL显示在Extras页面")
                return True
            
            # 检查方法3：导航状态
            nav_state = self.get_navigation_state()
            if nav_state and 'Extras' in nav_state:
                extras_info = nav_state['Extras']
                if extras_info.get('current', False):
                    print(f"      ✓ 导航状态显示在Extras页面")
                    return True
            
            return False
            
        except Exception as e:
            print(f"      验证Extras页面时出错: {e}")
            return False
    
    def extract_extras_options(self):
        """
        提取Extras页面的选装件选项
        识别并分类所有选装件类别和详细信息
        
        Returns:
            list: 选装件选项列表
        """
        print("    🔍 提取Extras选项...")
        
        extras_options = []
        
        try:
            # 等待页面稳定
            time.sleep(2)
            
            # 方法1：查找Extras选项容器（多种可能的结构）
            extras_selectors = [
                # 可能的选装件选项容器
                '[data-testid*="extras"] [class*="Option"]',
                '[data-testid*="extra"] [class*="Option"]',
                '[class*="ExtrasOption"]',
                '[class*="ExtraOption"]',
                '[class*="ProductTile"][class*="extra" i]',
                '[class*="OptionTile"]',
                'div[class*="Option"] button',
                'div[role="button"][class*="extra" i]',
                # 通用选装件元素
                'button[class*="extra" i]',
                'div[data-cy*="extra" i]',
                'label[class*="extra" i]'
            ]
            
            found_options = []
            
            for selector in extras_selectors:
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    print(f"      🔍 选择器 '{selector}' 找到 {len(elements)} 个元素")
                    
                    for element in elements:
                        if element.is_displayed():
                            option_data = self.extract_extras_option_data(element)
                            if option_data:
                                # 检查是否已存在相同的选装件
                                existing_names = [opt.get('name', '') for opt in found_options]
                                if option_data['name'] not in existing_names:
                                    found_options.append(option_data)
                                    print(f"      ✓ 找到Extras选项: {option_data['name']} - {option_data['price']}")
                except Exception as e:
                    print(f"      ⚠️  选择器 '{selector}' 处理时出错: {e}")
                    continue
            
            extras_options = found_options
            
            # 如果没找到，尝试通用的ProductTile结构
            if not extras_options:
                print("      🔍 尝试通用ProductTile结构...")
                extras_options = self.extract_extras_from_product_tiles()
            
            # 如果仍没找到，创建默认选项
            if not extras_options:
                print(f"      ⚠️  未找到Extras选项，使用默认值")
                extras_options = [
                    {'name': 'Blind Spot Information System', 'price': '+£450', 'description': 'Safety feature', 'category': 'Safety'},
                    {'name': 'Premium Audio System', 'price': '+£750', 'description': 'Entertainment system', 'category': 'Entertainment'},
                    {'name': 'Winter Pack', 'price': '+£300', 'description': 'Heated seats and steering wheel', 'category': 'Comfort'}
                ]
            
            return extras_options
            
        except Exception as e:
            print(f"      ❌ 提取Extras选项时出错: {e}")
            return []
    
    def extract_extras_option_data(self, element):
        """
        从选装件选项元素中提取数据
        
        Args:
            element (WebElement): 选装件选项元素
            
        Returns:
            dict or None: 选装件选项数据
        """
        try:
            name = ''
            price = ''
            description = ''
            category = ''
            
            # 方法1：从data属性获取信息
            data_cy = element.get_attribute('data-cy')
            if data_cy:
                name = data_cy
            
            # 方法2：从元素文本获取信息
            element_text = element.text.strip()
            if element_text:
                lines = element_text.split('\n')
                
                for line in lines:
                    line = line.strip()
                    if line:
                        # 识别价格
                        if '£' in line or '$' in line or '€' in line:
                            if not price:
                                price = line
                        # 识别名称（通常是最长的非价格行）
                        elif not name and len(line) > 5:
                            name = line
                        # 其他作为描述
                        elif not description and len(line) > 10:
                            description = line
            
            # 方法3：查找子元素
            if not name or not price:
                try:
                    # 查找标题元素
                    title_selectors = [
                        'h1, h2, h3, h4, h5, h6',
                        '[class*="title"]',
                        '[class*="name"]',
                        '[class*="label"]',
                        'strong',
                        '.text-lg, .text-xl'
                    ]
                    
                    for selector in title_selectors:
                        title_elements = element.find_elements(By.CSS_SELECTOR, selector)
                        for title_elem in title_elements:
                            if title_elem.is_displayed():
                                title_text = title_elem.text.strip()
                                if title_text and not name:
                                    name = title_text
                                    break
                        if name:
                            break
                    
                    # 查找价格元素
                    price_selectors = [
                        '[class*="price"]',
                        '[class*="cost"]',
                        '[class*="amount"]',
                        'span'
                    ]
                    
                    for selector in price_selectors:
                        price_elements = element.find_elements(By.CSS_SELECTOR, selector)
                        for price_elem in price_elements:
                            if price_elem.is_displayed():
                                price_text = price_elem.text.strip()
                                if price_text and ('£' in price_text or '$' in price_text) and not price:
                                    price = price_text
                                    break
                        if price:
                            break
                            
                except Exception:
                    pass
            
            # 尝试推断类别
            if name:
                name_lower = name.lower()
                if any(word in name_lower for word in ['safety', 'assist', 'brake', 'sensor', 'camera']):
                    category = 'Safety'
                elif any(word in name_lower for word in ['audio', 'sound', 'music', 'radio', 'entertainment']):
                    category = 'Entertainment'
                elif any(word in name_lower for word in ['seat', 'heated', 'comfort', 'climate']):
                    category = 'Comfort'
                elif any(word in name_lower for word in ['wheel', 'alloy', 'tire', 'rim']):
                    category = 'Wheels'
                else:
                    category = 'Other'
            
            # 验证数据
            if name and len(name) > 2:
                return {
                    'name': name,
                    'price': price if price else 'Optional',
                    'description': description,
                    'category': category,
                    'element_text': element_text
                }
            
            return None
            
        except Exception as e:
            print(f"        提取Extras选项数据时出错: {e}")
            return None
    
    def extract_extras_from_product_tiles(self):
        """
        从通用ProductTile结构中提取选装件信息
        
        Returns:
            list: 选装件选项列表
        """
        try:
            product_tiles = self.driver.find_elements(By.CSS_SELECTOR, 'div[class*="ProductTile"]')
            extras_options = []
            
            for tile in product_tiles:
                if tile.is_displayed():
                    tile_text = tile.text.strip().lower()
                    # 检查是否可能是选装件（包含相关关键词）
                    extras_keywords = ['pack', 'system', 'assist', 'kit', 'option', 'upgrade', 'premium']
                    
                    if any(keyword in tile_text for keyword in extras_keywords):
                        option_data = self.extract_extras_option_data(tile)
                        if option_data:
                            extras_options.append(option_data)
                            print(f"      ✓ 从ProductTile提取: {option_data['name']} - {option_data['price']}")
            
            return extras_options
            
        except Exception as e:
            print(f"      从ProductTile提取选装件时出错: {e}")
            return []
    
    def update_car_objects_with_extras_data(self, car_series, target_model, extras_data):
        """
        将Extras数据更新到每个CarObject中
        
        Args:
            car_series (CarSeries): 车系对象
            target_model (str): 目标车型名称
            extras_data (list): 选装件数据列表
        """
        print(f"    🔄 为 {target_model} 的每个CarObject添加Extras数据...")
        
        try:
            updated_objects = 0
            
            # 将extras_data转换为CarExtras对象列表
            car_extras_list = []
            for extra in extras_data:
                extra_name = extra.get('name', '')
                extra_price = extra.get('price', 'Optional')
                
                if extra_name:
                    car_extra = CarExtras(extra_name, extra_price)
                    car_extras_list.append(car_extra)
            
            # 遍历所有CarObject，找到匹配的车型
            for car_object in car_series.car_object_list:
                if car_object.model_name.lower() == target_model.lower():
                    # 将选装件数据添加到CarObject中
                    car_object.extras = [extra.to_dict() for extra in car_extras_list]
                    updated_objects += 1
                    
                    print(f"      ✓ 为 {target_model} + {car_object.drive} 添加 {len(car_extras_list)} 个选装件选项")
            
            print(f"    ✅ 共更新了 {updated_objects} 个CarObject，添加了 {len(car_extras_list)} 个选装件选项")
            
        except Exception as e:
            print(f"    ❌ 更新Extras数据时出错: {e}")
